summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.rubocop.yml2
-rw-r--r--CHANGELOG78
-rw-r--r--GITLAB_SHELL_VERSION2
-rw-r--r--Gemfile110
-rw-r--r--Gemfile.lock64
-rw-r--r--app/assets/images/emoji.pngbin263346 -> 1025831 bytes
-rw-r--r--app/assets/images/emoji@2x.pngbin689076 -> 2492919 bytes
-rw-r--r--app/assets/javascripts/application.js.coffee2
-rw-r--r--app/assets/javascripts/build.coffee (renamed from app/assets/javascripts/ci/build.coffee)14
-rw-r--r--app/assets/javascripts/ci/application.js.coffee12
-rw-r--r--app/assets/javascripts/ci/projects.js.coffee3
-rw-r--r--app/assets/javascripts/diff.js.coffee5
-rw-r--r--app/assets/javascripts/dispatcher.js.coffee3
-rw-r--r--app/assets/javascripts/dropzone_input.js.coffee4
-rw-r--r--app/assets/javascripts/files_comment_button.js.coffee97
-rw-r--r--app/assets/javascripts/flash.js.coffee30
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js.coffee2
-rw-r--r--app/assets/javascripts/gl_dropdown.js.coffee4
-rw-r--r--app/assets/javascripts/issuable.js.coffee8
-rw-r--r--app/assets/javascripts/labels_select.js.coffee10
-rw-r--r--app/assets/javascripts/lib/cropper.js.coffee1
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js.coffee7
-rw-r--r--app/assets/javascripts/lib/utils/datetime_utility.js.coffee4
-rw-r--r--app/assets/javascripts/lib/utils/text_utility.js.coffee5
-rw-r--r--app/assets/javascripts/merge_request_tabs.js.coffee3
-rw-r--r--app/assets/javascripts/milestone_select.js.coffee6
-rw-r--r--app/assets/javascripts/namespace_select.js.coffee79
-rw-r--r--app/assets/javascripts/notes.js.coffee69
-rw-r--r--app/assets/javascripts/profile/application.js.coffee2
-rw-r--r--app/assets/javascripts/profile/gl_crop.js.coffee (renamed from app/assets/javascripts/gl_crop.js.coffee)0
-rw-r--r--app/assets/javascripts/profile/profile.js.coffee (renamed from app/assets/javascripts/profile.js.coffee)3
-rw-r--r--app/assets/javascripts/protected_branch_select.js.coffee40
-rw-r--r--app/assets/javascripts/protected_branches.js.coffee3
-rw-r--r--app/assets/javascripts/single_file_diff.js.coffee54
-rw-r--r--app/assets/javascripts/users/calendar.js.coffee5
-rw-r--r--app/assets/javascripts/users_select.js.coffee12
-rw-r--r--app/assets/stylesheets/framework/blank.scss23
-rw-r--r--app/assets/stylesheets/framework/blocks.scss3
-rw-r--r--app/assets/stylesheets/framework/buttons.scss18
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss7
-rw-r--r--app/assets/stylesheets/framework/files.scss2
-rw-r--r--app/assets/stylesheets/framework/flash.scss22
-rw-r--r--app/assets/stylesheets/framework/gitlab-theme.scss11
-rw-r--r--app/assets/stylesheets/framework/lists.scss15
-rw-r--r--app/assets/stylesheets/framework/nav.scss10
-rw-r--r--app/assets/stylesheets/framework/sidebar.scss27
-rw-r--r--app/assets/stylesheets/framework/variables.scss12
-rw-r--r--app/assets/stylesheets/pages/admin.scss33
-rw-r--r--app/assets/stylesheets/pages/commits.scss2
-rw-r--r--app/assets/stylesheets/pages/diff.scss10
-rw-r--r--app/assets/stylesheets/pages/groups.scss33
-rw-r--r--app/assets/stylesheets/pages/issues.scss4
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss3
-rw-r--r--app/assets/stylesheets/pages/projects.scss387
-rw-r--r--app/assets/stylesheets/pages/search.scss2
-rw-r--r--app/controllers/admin/application_settings_controller.rb2
-rw-r--r--app/controllers/admin/projects_controller.rb5
-rw-r--r--app/controllers/concerns/diff_for_path.rb25
-rw-r--r--app/controllers/help_controller.rb10
-rw-r--r--app/controllers/import/gitlab_projects_controller.rb5
-rw-r--r--app/controllers/projects/artifacts_controller.rb5
-rw-r--r--app/controllers/projects/blob_controller.rb2
-rw-r--r--app/controllers/projects/commit_controller.rb50
-rw-r--r--app/controllers/projects/compare_controller.rb48
-rw-r--r--app/controllers/projects/git_http_controller.rb24
-rw-r--r--app/controllers/projects/merge_requests_controller.rb173
-rw-r--r--app/controllers/projects/notes_controller.rb21
-rw-r--r--app/controllers/projects/protected_branches_controller.rb26
-rw-r--r--app/controllers/projects_controller.rb4
-rw-r--r--app/helpers/appearances_helper.rb4
-rw-r--r--app/helpers/application_helper.rb11
-rw-r--r--app/helpers/application_settings_helper.rb22
-rw-r--r--app/helpers/branches_helper.rb2
-rw-r--r--app/helpers/button_helper.rb38
-rw-r--r--app/helpers/diff_helper.rb33
-rw-r--r--app/helpers/dropdowns_helper.rb2
-rw-r--r--app/helpers/issues_helper.rb2
-rw-r--r--app/helpers/members_helper.rb11
-rw-r--r--app/helpers/merge_requests_helper.rb10
-rw-r--r--app/helpers/notes_helper.rb90
-rw-r--r--app/helpers/projects_helper.rb16
-rw-r--r--app/helpers/search_helper.rb18
-rw-r--r--app/helpers/time_helper.rb7
-rw-r--r--app/helpers/workhorse_helper.rb15
-rw-r--r--app/models/ability.rb30
-rw-r--r--app/models/application_setting.rb4
-rw-r--r--app/models/award_emoji.rb2
-rw-r--r--app/models/ci/build.rb5
-rw-r--r--app/models/commit.rb7
-rw-r--r--app/models/commit_range.rb4
-rw-r--r--app/models/concerns/note_on_diff.rb52
-rw-r--r--app/models/deployment.rb6
-rw-r--r--app/models/diff_note.rb127
-rw-r--r--app/models/event.rb4
-rw-r--r--app/models/group.rb2
-rw-r--r--app/models/label.rb14
-rw-r--r--app/models/legacy_diff_note.rb69
-rw-r--r--app/models/merge_request.rb201
-rw-r--r--app/models/merge_request_diff.rb147
-rw-r--r--app/models/note.rb26
-rw-r--r--app/models/notification_setting.rb9
-rw-r--r--app/models/project.rb33
-rw-r--r--app/models/project_services/irker_service.rb10
-rw-r--r--app/models/project_services/jira_service.rb2
-rw-r--r--app/models/protected_branch.rb47
-rw-r--r--app/models/repository.rb16
-rw-r--r--app/models/sent_notification.rb58
-rw-r--r--app/models/user.rb4
-rw-r--r--app/services/audit_event_service.rb2
-rw-r--r--app/services/auth/container_registry_authentication_service.rb2
-rw-r--r--app/services/commits/change_service.rb2
-rw-r--r--app/services/compare_service.rb2
-rw-r--r--app/services/create_branch_service.rb10
-rw-r--r--app/services/create_release_service.rb4
-rw-r--r--app/services/create_snippet_service.rb10
-rw-r--r--app/services/create_tag_service.rb2
-rw-r--r--app/services/delete_branch_service.rb12
-rw-r--r--app/services/delete_tag_service.rb9
-rw-r--r--app/services/files/base_service.rb9
-rw-r--r--app/services/files/create_service.rb2
-rw-r--r--app/services/git_tag_push_service.rb1
-rw-r--r--app/services/issues/bulk_update_service.rb1
-rw-r--r--app/services/merge_requests/merge_service.rb2
-rw-r--r--app/services/merge_requests/merge_when_build_succeeds_service.rb2
-rw-r--r--app/services/merge_requests/post_merge_service.rb1
-rw-r--r--app/services/merge_requests/refresh_service.rb21
-rw-r--r--app/services/merge_requests/reopen_service.rb2
-rw-r--r--app/services/notes/diff_position_update_service.rb30
-rw-r--r--app/services/notification_service.rb2
-rw-r--r--app/services/projects/housekeeping_service.rb14
-rw-r--r--app/services/projects/import_export/export_service.rb4
-rw-r--r--app/services/projects/update_service.rb3
-rw-r--r--app/services/system_note_service.rb7
-rw-r--r--app/services/update_release_service.rb4
-rw-r--r--app/services/update_snippet_service.rb1
-rw-r--r--app/validators/addressable_url_validator.rb45
-rw-r--r--app/views/admin/abuse_reports/_abuse_report.html.haml4
-rw-r--r--app/views/admin/appearances/_form.html.haml2
-rw-r--r--app/views/admin/application_settings/_form.html.haml19
-rw-r--r--app/views/admin/deploy_keys/new.html.haml2
-rw-r--r--app/views/admin/groups/_group.html.haml42
-rw-r--r--app/views/admin/groups/index.html.haml57
-rw-r--r--app/views/admin/groups/show.html.haml2
-rw-r--r--app/views/admin/hooks/index.html.haml2
-rw-r--r--app/views/admin/projects/index.html.haml171
-rw-r--r--app/views/admin/projects/show.html.haml10
-rw-r--r--app/views/admin/users/_form.html.haml2
-rw-r--r--app/views/admin/users/_user.html.haml42
-rw-r--r--app/views/admin/users/index.html.haml170
-rw-r--r--app/views/errors/access_denied.html.haml2
-rw-r--r--app/views/explore/snippets/index.html.haml1
-rw-r--r--app/views/groups/group_members/_new_group_member.html.haml2
-rw-r--r--app/views/groups/milestones/index.html.haml1
-rw-r--r--app/views/groups/projects.html.haml1
-rw-r--r--app/views/help/show.html.haml2
-rw-r--r--app/views/help/ui.html.haml2
-rw-r--r--app/views/import/github/new.html.haml2
-rw-r--r--app/views/layouts/_flash.html.haml2
-rw-r--r--app/views/layouts/_page.html.haml5
-rw-r--r--app/views/layouts/header/_default.html.haml4
-rw-r--r--app/views/notify/note_merge_request_email.html.haml4
-rw-r--r--app/views/notify/repository_push_email.html.haml5
-rw-r--r--app/views/profiles/_head.html.haml3
-rw-r--r--app/views/profiles/accounts/show.html.haml1
-rw-r--r--app/views/profiles/audit_log.html.haml1
-rw-r--r--app/views/profiles/emails/index.html.haml1
-rw-r--r--app/views/profiles/keys/_form.html.haml2
-rw-r--r--app/views/profiles/keys/index.html.haml2
-rw-r--r--app/views/profiles/keys/show.html.haml1
-rw-r--r--app/views/profiles/notifications/show.html.haml1
-rw-r--r--app/views/profiles/personal_access_tokens/index.html.haml1
-rw-r--r--app/views/profiles/preferences/show.html.haml5
-rw-r--r--app/views/profiles/show.html.haml2
-rw-r--r--app/views/profiles/two_factor_auths/show.html.haml3
-rw-r--r--app/views/projects/_bitbucket_import_modal.html.haml2
-rw-r--r--app/views/projects/_builds_settings.html.haml2
-rw-r--r--app/views/projects/_gitlab_import_modal.html.haml2
-rw-r--r--app/views/projects/_home_panel.html.haml52
-rw-r--r--app/views/projects/_last_commit.html.haml19
-rw-r--r--app/views/projects/_last_push.html.haml4
-rw-r--r--app/views/projects/_merge_request_settings.html.haml2
-rw-r--r--app/views/projects/blob/edit.html.haml2
-rw-r--r--app/views/projects/builds/index.html.haml2
-rw-r--r--app/views/projects/builds/show.html.haml2
-rw-r--r--app/views/projects/buttons/_fork.html.haml5
-rw-r--r--app/views/projects/ci/pipelines/_pipeline.html.haml2
-rw-r--r--app/views/projects/commit/_ci_stage.html.haml2
-rw-r--r--app/views/projects/commit/show.html.haml3
-rw-r--r--app/views/projects/commits/_commit.html.haml2
-rw-r--r--app/views/projects/deploy_keys/_form.html.haml2
-rw-r--r--app/views/projects/diffs/_content.html.haml29
-rw-r--r--app/views/projects/diffs/_diffs.html.haml8
-rw-r--r--app/views/projects/diffs/_file.html.haml47
-rw-r--r--app/views/projects/diffs/_file_header.html.haml25
-rw-r--r--app/views/projects/diffs/_image.html.haml11
-rw-r--r--app/views/projects/diffs/_line.html.haml21
-rw-r--r--app/views/projects/diffs/_match_line_parallel.html.haml4
-rw-r--r--app/views/projects/diffs/_parallel_view.html.haml35
-rw-r--r--app/views/projects/diffs/_text_file.html.haml15
-rw-r--r--app/views/projects/diffs/_warning.html.haml3
-rw-r--r--app/views/projects/edit.html.haml2
-rw-r--r--app/views/projects/environments/index.html.haml2
-rw-r--r--app/views/projects/environments/new.html.haml2
-rw-r--r--app/views/projects/environments/show.html.haml2
-rw-r--r--app/views/projects/issues/index.html.haml48
-rw-r--r--app/views/projects/merge_requests/_show.html.haml4
-rw-r--r--app/views/projects/merge_requests/show/_how_to_merge.html.haml6
-rw-r--r--app/views/projects/merge_requests/show/_mr_title.html.haml8
-rw-r--r--app/views/projects/merge_requests/widget/_heading.html.haml10
-rw-r--r--app/views/projects/merge_requests/widget/_open.html.haml6
-rw-r--r--app/views/projects/merge_requests/widget/open/_accept.html.haml2
-rw-r--r--app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml2
-rw-r--r--app/views/projects/new.html.haml2
-rw-r--r--app/views/projects/notes/_diff_notes_with_reply.html.haml3
-rw-r--r--app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml6
-rw-r--r--app/views/projects/notes/_form.html.haml1
-rw-r--r--app/views/projects/notes/_hints.html.haml2
-rw-r--r--app/views/projects/notes/_notes_with_form.html.haml2
-rw-r--r--app/views/projects/notes/discussions/_diff_with_notes.html.haml35
-rw-r--r--app/views/projects/notes/discussions/_notes.html.haml3
-rw-r--r--app/views/projects/pipelines/index.html.haml4
-rw-r--r--app/views/projects/project_members/_new_project_member.html.haml2
-rw-r--r--app/views/projects/protected_branches/_branches_list.html.haml33
-rw-r--r--app/views/projects/protected_branches/_dropdown.html.haml17
-rw-r--r--app/views/projects/protected_branches/_matching_branch.html.haml9
-rw-r--r--app/views/projects/protected_branches/_protected_branch.html.haml21
-rw-r--r--app/views/projects/protected_branches/index.html.haml28
-rw-r--r--app/views/projects/protected_branches/show.html.haml25
-rw-r--r--app/views/projects/show.html.haml101
-rw-r--r--app/views/projects/snippets/_actions.html.haml42
-rw-r--r--app/views/projects/snippets/index.html.haml6
-rw-r--r--app/views/projects/tags/index.html.haml28
-rw-r--r--app/views/shared/_clone_panel.html.haml23
-rw-r--r--app/views/shared/_labels_row.html.haml7
-rw-r--r--app/views/shared/_visibility_level.html.haml2
-rw-r--r--app/views/shared/icons/_issues.svg13
-rw-r--r--app/views/shared/icons/_issues.svg.erb4
-rw-r--r--app/views/shared/members/_access_request_buttons.html.haml2
-rw-r--r--app/views/shared/members/_member.html.haml85
-rw-r--r--app/views/shared/milestones/_summary.html.haml1
-rw-r--r--app/views/shared/projects/_dropdown.html.haml17
-rw-r--r--app/views/shared/web_hooks/_form.html.haml2
-rw-r--r--app/views/snippets/_actions.html.haml41
-rw-r--r--app/views/users/show.html.haml5
-rw-r--r--app/workers/emails_on_push_worker.rb16
-rw-r--r--app/workers/git_garbage_collect_worker.rb14
-rw-r--r--app/workers/gitlab_shell_one_shot_worker.rb10
-rw-r--r--config/application.rb1
-rw-r--r--config/initializers/health_check.rb13
-rw-r--r--config/initializers/metrics.rb2
-rw-r--r--config/routes.rb20
-rw-r--r--db/migrate/20160508202603_add_head_commit_id_to_merge_request_diffs.rb5
-rw-r--r--db/migrate/20160508215920_add_positions_to_diff_notes.rb6
-rw-r--r--db/migrate/20160516224534_add_start_commit_id_to_merge_request_diffs.rb5
-rw-r--r--db/migrate/20160522215720_add_note_type_and_position_to_sent_notification.rb22
-rw-r--r--db/migrate/20160608211215_add_user_default_external_to_application_settings.rb13
-rw-r--r--db/migrate/20160615173316_add_enabled_git_access_protocols_to_application_settings.rb11
-rw-r--r--db/migrate/20160616102642_remove_duplicated_keys.rb4
-rw-r--r--db/migrate/20160703180340_add_index_on_award_emoji_user_and_name.rb11
-rw-r--r--db/migrate/20160705163108_remove_requesters_that_are_owners.rb40
-rw-r--r--db/schema.rb13
-rw-r--r--doc/README.md3
-rw-r--r--doc/administration/access_restrictions.md38
-rw-r--r--doc/administration/auth/ldap.md42
-rw-r--r--doc/administration/custom_hooks.md57
-rw-r--r--doc/administration/img/access_restrictions.pngbin0 -> 317529 bytes
-rw-r--r--doc/administration/img/custom_hooks_error_msg.pngbin0 -> 159486 bytes
-rw-r--r--doc/administration/img/restricted_url.pngbin0 -> 188210 bytes
-rw-r--r--doc/api/groups.md247
-rw-r--r--doc/api/merge_requests.md48
-rw-r--r--doc/api/projects.md119
-rw-r--r--doc/api/settings.md1
-rw-r--r--doc/ci/examples/php.md2
-rw-r--r--doc/ci/yaml/README.md4
-rw-r--r--doc/development/ui_guide.md5
-rw-r--r--doc/hooks/custom_hooks.md40
-rw-r--r--doc/install/database_mysql.md2
-rw-r--r--doc/install/installation.md6
-rw-r--r--doc/integration/github.md2
-rw-r--r--doc/integration/shibboleth.md2
-rw-r--r--doc/markdown/markdown.md34
-rw-r--r--doc/permissions/permissions.md3
-rw-r--r--doc/update/8.8-to-8.9.md24
-rw-r--r--doc/update/8.9-to-8.10.md191
-rw-r--r--doc/workflow/protected_branches.md28
-rw-r--r--doc/workflow/protected_branches/protected_branches1.pngbin155815 -> 195061 bytes
-rw-r--r--doc/workflow/protected_branches/protected_branches2.pngbin23208 -> 41179 bytes
-rw-r--r--doc/workflow/protected_branches/protected_branches3.pngbin0 -> 110160 bytes
-rw-r--r--features/admin/projects.feature4
-rw-r--r--features/dashboard/dashboard.feature1
-rw-r--r--features/project/commits/commits.feature5
-rw-r--r--features/project/commits/diff_comments.feature4
-rw-r--r--features/project/merge_requests.feature7
-rw-r--r--features/steps/admin/groups.rb3
-rw-r--r--features/steps/admin/projects.rb9
-rw-r--r--features/steps/dashboard/help.rb2
-rw-r--r--features/steps/profile/profile.rb7
-rw-r--r--features/steps/project/builds/artifacts.rb14
-rw-r--r--features/steps/project/commits/commits.rb19
-rw-r--r--features/steps/project/merge_requests.rb5
-rw-r--r--features/steps/shared/diff_note.rb33
-rw-r--r--features/steps/shared/project.rb5
-rw-r--r--fixtures/emojis/digests.json4078
-rw-r--r--lib/api/entities.rb21
-rw-r--r--lib/api/internal.rb7
-rw-r--r--lib/api/merge_requests.rb4
-rw-r--r--lib/banzai/filter/blockquote_fence_filter.rb71
-rw-r--r--lib/banzai/filter/emoji_filter.rb4
-rw-r--r--lib/banzai/filter/label_reference_filter.rb8
-rw-r--r--lib/banzai/object_renderer.rb10
-rw-r--r--lib/banzai/pipeline/pre_process_pipeline.rb3
-rw-r--r--lib/banzai/redactor.rb37
-rw-r--r--lib/banzai/reference_parser/base_parser.rb36
-rw-r--r--lib/banzai/reference_parser/user_parser.rb5
-rw-r--r--lib/gitlab/current_settings.rb1
-rw-r--r--lib/gitlab/diff/diff_refs.rb36
-rw-r--r--lib/gitlab/diff/file.rb101
-rw-r--r--lib/gitlab/diff/highlight.rb31
-rw-r--r--lib/gitlab/diff/line.rb16
-rw-r--r--lib/gitlab/diff/line_mapper.rb64
-rw-r--r--lib/gitlab/diff/parallel_diff.rb32
-rw-r--r--lib/gitlab/diff/position.rb155
-rw-r--r--lib/gitlab/diff/position_tracer.rb168
-rw-r--r--lib/gitlab/email/message/repository_push.rb8
-rw-r--r--lib/gitlab/email/receiver.rb10
-rw-r--r--lib/gitlab/emoji.rb21
-rw-r--r--lib/gitlab/git/hook.rb13
-rw-r--r--lib/gitlab/git_access.rb11
-rw-r--r--lib/gitlab/github_import/branch_formatter.rb12
-rw-r--r--lib/gitlab/github_import/importer.rb4
-rw-r--r--lib/gitlab/github_import/pull_request_formatter.rb4
-rw-r--r--lib/gitlab/graphs/commits.rb2
-rw-r--r--lib/gitlab/import_export/command_line_util.rb3
-rw-r--r--lib/gitlab/import_export/project_tree_restorer.rb9
-rw-r--r--lib/gitlab/import_export/saver.rb1
-rw-r--r--lib/gitlab/metrics/subscribers/rails_cache.rb22
-rw-r--r--lib/gitlab/protocol_access.rb13
-rw-r--r--lib/gitlab/sidekiq_middleware/memory_killer.rb4
-rw-r--r--lib/gitlab/timeless.rb16
-rw-r--r--lib/gitlab/url_sanitizer.rb12
-rw-r--r--lib/gitlab/workhorse.rb24
-rw-r--r--lib/rouge/formatters/html_gitlab.rb16
-rw-r--r--lib/tasks/gemojione.rake2
-rw-r--r--spec/controllers/admin/projects_controller_spec.rb4
-rw-r--r--spec/controllers/commit_controller_spec.rb246
-rw-r--r--spec/controllers/help_controller_spec.rb13
-rw-r--r--spec/controllers/projects/commit_controller_spec.rb289
-rw-r--r--spec/controllers/projects/compare_controller_spec.rb69
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb252
-rw-r--r--spec/factories/notes.rb33
-rw-r--r--spec/factories/notification_settings.rb8
-rw-r--r--spec/factories/projects.rb2
-rw-r--r--spec/features/admin/admin_abuse_reports_spec.rb30
-rw-r--r--spec/features/admin/admin_disables_git_access_protocol_spec.rb66
-rw-r--r--spec/features/admin/admin_users_spec.rb8
-rw-r--r--spec/features/expand_collapse_diffs_spec.rb207
-rw-r--r--spec/features/groups/members/member_cannot_request_access_to_his_project_spec.rb16
-rw-r--r--spec/features/help_pages_spec.rb2
-rw-r--r--spec/features/issues/filter_issues_spec.rb4
-rw-r--r--spec/features/merge_requests/created_from_fork_spec.rb2
-rw-r--r--spec/features/merge_requests/diffs_spec.rb25
-rw-r--r--spec/features/merge_requests/merge_when_build_succeeds_spec.rb4
-rw-r--r--spec/features/merge_requests/only_allow_merge_if_build_succeeds.rb2
-rw-r--r--spec/features/notes_on_merge_requests_spec.rb31
-rw-r--r--spec/features/pipelines_spec.rb2
-rw-r--r--spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb6
-rw-r--r--spec/features/projects/import_export/import_file_spec.rb17
-rw-r--r--spec/features/projects/labels/update_prioritization_spec.rb2
-rw-r--r--spec/features/projects/members/group_member_cannot_request_access_to_his_group_project_spec.rb3
-rw-r--r--spec/features/projects/members/member_cannot_request_access_to_his_project_spec.rb16
-rw-r--r--spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb16
-rw-r--r--spec/features/protected_branches_spec.rb84
-rw-r--r--spec/features/search_spec.rb2
-rw-r--r--spec/fixtures/blockquote_fence_after.md115
-rw-r--r--spec/fixtures/blockquote_fence_before.md131
-rw-r--r--spec/fixtures/parallel_diff_result.yml504
-rw-r--r--spec/helpers/diff_helper_spec.rb21
-rw-r--r--spec/helpers/members_helper_spec.rb66
-rw-r--r--spec/javascripts/fixtures/issues_show.html.haml2
-rw-r--r--spec/lib/banzai/filter/blockquote_fence_filter_spec.rb14
-rw-r--r--spec/lib/banzai/filter/label_reference_filter_spec.rb50
-rw-r--r--spec/lib/banzai/object_renderer_spec.rb8
-rw-r--r--spec/lib/banzai/redactor_spec.rb24
-rw-r--r--spec/lib/banzai/reference_parser/base_parser_spec.rb75
-rw-r--r--spec/lib/gitlab/diff/file_spec.rb2
-rw-r--r--spec/lib/gitlab/diff/highlight_spec.rb6
-rw-r--r--spec/lib/gitlab/diff/line_mapper_spec.rb137
-rw-r--r--spec/lib/gitlab/diff/parallel_diff_spec.rb3
-rw-r--r--spec/lib/gitlab/diff/position_spec.rb341
-rw-r--r--spec/lib/gitlab/diff/position_tracer_spec.rb1758
-rw-r--r--spec/lib/gitlab/git/hook_spec.rb70
-rw-r--r--spec/lib/gitlab/git_access_spec.rb39
-rw-r--r--spec/lib/gitlab/git_access_wiki_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/branch_formatter_spec.rb19
-rw-r--r--spec/lib/gitlab/github_import/pull_request_formatter_spec.rb18
-rw-r--r--spec/lib/gitlab/graphs/commits_spec.rb39
-rw-r--r--spec/lib/gitlab/import_export/project.json13
-rw-r--r--spec/lib/gitlab/import_export/project_tree_restorer_spec.rb18
-rw-r--r--spec/lib/gitlab/import_export/project_tree_saver_spec.rb2
-rw-r--r--spec/lib/gitlab/metrics/subscribers/rails_cache_spec.rb103
-rw-r--r--spec/lib/gitlab/note_data_builder_spec.rb4
-rw-r--r--spec/lib/gitlab/url_builder_spec.rb8
-rw-r--r--spec/lib/gitlab/url_sanitizer_spec.rb6
-rw-r--r--spec/mailers/notify_spec.rb4
-rw-r--r--spec/models/diff_note_spec.rb191
-rw-r--r--spec/models/event_spec.rb32
-rw-r--r--spec/models/label_spec.rb13
-rw-r--r--spec/models/legacy_diff_note_spec.rb16
-rw-r--r--spec/models/merge_request_diff_spec.rb47
-rw-r--r--spec/models/merge_request_spec.rb94
-rw-r--r--spec/models/note_spec.rb14
-rw-r--r--spec/models/notification_setting_spec.rb17
-rw-r--r--spec/models/project_spec.rb78
-rw-r--r--spec/models/protected_branch_spec.rb125
-rw-r--r--spec/models/repository_spec.rb4
-rw-r--r--spec/models/user_spec.rb21
-rw-r--r--spec/requests/api/groups_spec.rb19
-rw-r--r--spec/requests/api/internal_spec.rb71
-rw-r--r--spec/requests/api/issues_spec.rb40
-rw-r--r--spec/requests/api/labels_spec.rb10
-rw-r--r--spec/requests/api/merge_requests_spec.rb34
-rw-r--r--spec/requests/api/projects_spec.rb40
-rw-r--r--spec/routing/routing_spec.rb22
-rw-r--r--spec/services/notes/diff_position_update_service_spec.rb175
-rw-r--r--spec/services/notification_service_spec.rb24
-rw-r--r--spec/services/projects/housekeeping_service_spec.rb4
-rw-r--r--spec/services/system_note_service_spec.rb2
-rw-r--r--spec/support/capybara_helpers.rb8
-rw-r--r--spec/support/test_env.rb29
-rw-r--r--spec/workers/git_garbage_collect_worker_spec.rb24
-rw-r--r--vendor/gitignore/Android.gitignore1
-rw-r--r--vendor/gitignore/C++.gitignore3
-rw-r--r--vendor/gitignore/C.gitignore3
-rw-r--r--vendor/gitignore/Gradle.gitignore2
-rw-r--r--vendor/gitignore/LICENSE140
-rw-r--r--vendor/gitignore/Node.gitignore1
-rw-r--r--vendor/gitignore/TeX.gitignore3
-rw-r--r--vendor/gitlab-ci-yml/Maven.gitlab-ci.yml102
-rw-r--r--vendor/gitlab-ci-yml/Pages/Brunch.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/brunch.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Doxygen.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/doxygen.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/HTML.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/html.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Harp.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/harp.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Hexo.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/hexo.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Hugo.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/hugo.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Hyde.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/hyde.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Jekyll.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/jekyll.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Lektor.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/lektor.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Metalsmith.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/metalsmith.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Middleman.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/middleman.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Nanoc.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/nanoc.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Octopress.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/octopress.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Pelican.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/pelican.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml15
-rw-r--r--vendor/gitlab-ci-yml/Rust.gitlab-ci.yml23
-rw-r--r--vendor/gitlab-ci-yml/Scala.gitlab-ci.yml22
455 files changed, 12674 insertions, 4858 deletions
diff --git a/.rubocop.yml b/.rubocop.yml
index cd13f581517..3aac8401848 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -284,7 +284,7 @@ Style/IfWithSemicolon:
# Checks that conditional statements do not have an identical line at the
# end of each branch, which can validly be moved out of the conditional.
Style/IdenticalConditionalBranches:
- Enabled: false
+ Enabled: true
# Checks the indentation of the first line of the right-hand-side of a
# multi-line assignment.
diff --git a/CHANGELOG b/CHANGELOG
index 98bd11af833..3db8fa142df 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,52 +1,102 @@
Please view this file on the master branch, on stable branches it's out of date.
v 8.10.0 (unreleased)
+ - Expose {should,force}_remove_source_branch (Ben Boeckel)
- Fix projects dropdown loading performance with a simplified api cal. !5113 (tiagonbotelho)
- Fix commit builds API, return all builds for all pipelines for given commit. !4849
- Replace Haml with Hamlit to make view rendering faster. !3666
+ - Expire the branch cache after `git gc` runs
- Refactor repository paths handling to allow multiple git mount points
+ - Optimize system note visibility checking by memoizing the visible reference count !5070
- Add Application Setting to configure default Repository Path for new projects
+ - Remove pinTo from Flash and make inline flash messages look nicer !4854 (winniehell)
- Wrap code blocks on Activies and Todos page. !4783 (winniehell)
- Align flash messages with left side of page content !4959 (winniehell)
+ - Display tooltip for "Copy to Clipboard" button !5164 (winniehell)
- Display last commit of deleted branch in push events !4699 (winniehell)
+ - Escape file extension when parsing search results !5141 (winniehell)
- Apply the trusted_proxies config to the rack request object for use with rack_attack
- Add Sidekiq queue duration to transaction metrics.
- Add a new column `artifacts_size` to table `ci_builds` !4964
- Let Workhorse serve format-patch diffs
+ - Added day name to contribution calendar tooltips
- Make images fit to the size of the viewport !4810
- Fix check for New Branch button on Issue page !4630 (winniehell)
- Fix MR-auto-close text added to description. !4836
+ - Fix issue, preventing users w/o push access to sort tags !5105 (redetection)
+ - Add Spring EmojiOne updates.
+ - Add syntax for multiline blockquote using `>>>` fence !3954
+ - Fix viewing notification settings when a project is pending deletion
- Fix pagination when sorting by columns with lots of ties (like priority)
+ - The Markdown reference parsers now re-use query results to prevent running the same queries multiple times !5020
+ - Updated project header design
- Exclude email check from the standard health check
+ - Updated layout for Projects, Groups, Users on Admin area !4424
- Fix changing issue state columns in milestone view
+ - Update health_check gem to version 2.1.0
- Add notification settings dropdown for groups
+ - Wildcards for protected branches. !4665
- Allow importing from Github using Personal Access Tokens. (Eric K Idema)
- API: Todos !3188 (Robert Schilling)
+ - API: Expose shared groups for projects and shared projects for groups !5050 (Robert Schilling)
+ - Add "Enabled Git access protocols" to Application Settings
+ - Diffs will create button/diff form on demand no on server side
+ - Reduce size of HTML used by diff comment forms
- Fix user creation with stronger minimum password requirements !4054 (nathan-pmt)
+ - Only show New Snippet button to users that can create snippets.
- PipelinesFinder uses git cache data
+ - Throttle the update of `project.pushes_since_gc` to 1 minute.
+ - Allow expanding and collapsing files in diff view (!4990)
+ - Collapse large diffs by default (!4990)
- Check for conflicts with existing Project's wiki path when creating a new project.
+ - Show last push widget in upstream after push to fork
- Don't instantiate a git tree on Projects show default view
+ - Bump Rinku to 2.0.0
- Remove unused front-end variable -> default_issues_tracker
- Better caching of git calls on ProjectsController#show.
+ - Avoid to retrieve MR closes_issues as much as possible.
- Add API endpoint for a group issues !4520 (mahcsig)
- Add Bugzilla integration !4930 (iamtjg)
+ - Instrument Rinku usage
+ - Be explicit to define merge request discussion variables
- Metrics for Rouge::Plugins::Redcarpet and Rouge::Formatters::HTMLGitlab
+ - RailsCache metris now includes fetch_hit/fetch_miss and read_hit/read_miss info.
- Allow [ci skip] to be in any case and allow [skip ci]. !4785 (simon_w)
+ - Set import_url validation to be more strict
+ - Memoize MR merged/closed events retrieval
+ - Don't render discussion notes when requesting diff tab through AJAX
- Add basic system information like memory and disk usage to the admin panel
- Don't garbage collect commits that have related DB records like comments
- More descriptive message for git hooks and file locks
- Handle custom Git hook result in GitLab UI
-
-v 8.9.4 (unreleased)
- - Ensure references to private repos aren't shown to logged-out users
-v 8.9.5 (unreleased)
+ - Allow '?', or '&' for label names
+ - Fix importer for GitHub Pull Requests when a branch was reused across Pull Requests
+ - Add date when user joined the team on the member page
+ - Fix 404 redirect after validation fails importing a GitLab project
+ - Fix 404 redirect after validation fails importing a GitLab project
+ - Added setting to set new users by default as external !4545 (Dravere)
+ - Add min value for project limit field on user's form !3622 (jastkand)
+ - Add reminder to not paste private SSH keys !4399 (Ingo Blechschmidt)
+ - Remove duplicate `description` field in `MergeRequest` entities (Ben Boeckel)
+ - Style of import project buttons were fixed in the new project page. !5183 (rdemirbay)
+
+v 8.9.6 (unreleased)
+ - Fix importing of events under notes for GitLab projects
+
+v 8.9.5
+ - Add more debug info to import/export and memory killer. !5108
+ - Fixed avatar alignment in new MR view. !5095
+ - Fix diff comments not showing up in activity feed. !5069
+ - Add index on both Award Emoji user and name. !5061
+ - Downgrade to Redis 3.2.2 due to massive memory leak with Sidekiq. !5056
+ - Re-enable import button when import process fails due to namespace already being taken. !5053
+ - Fix snippets comments not displayed. !5045
+ - Fix emoji paths in relative root configurations. !5027
+ - Fix issues importing events in Import/Export. !4987
+ - Fixed 'use shortcuts' button on docs. !4979
+ - Admin should be able to turn shared runners into specific ones. !4961
+ - Update RedCloth to 4.3.2 for CVE-2012-6684. !4929 (Takuya Noguchi)
- Improve the request / withdraw access button. !4860
- - Fix assigning shared runners as admins. !4961
- - Show "locked" label for locked runners on runners admin. !4961
- - Downgrade to Redis 3.2.2 due to massive memory leak with Sidekiq
- - Fixes issues importing events in Import/Export. Import/Export version bumped to 0.1.1
- - Fix import button disabled when import process fail due to the namespace already been taken.
- - Security: Update RedCloth to 4.3.2 (Takuya Noguchi)
v 8.9.4
- Fix privilege escalation issue with OAuth external users.
@@ -76,7 +126,7 @@ v 8.9.3
- Removed fade when filtering results. !4932
- Fix missing avatar on system notes. !4954
- Reduce overhead and optimize ProjectTeam#max_member_access performance. !4973
- - Use update_columns to by_pass all the dirty code on active_record. !4985
+ - Use update_columns to bypass all the dirty code on active_record. !4985
- Fix restore Rake task warning message output !4980
v 8.9.2
@@ -2580,13 +2630,13 @@ v 6.5.0
- Files API supports base64 encoded content (sponsored by O'Reilly Media)
- Added support for Go's repository retrieval (Bruno Albuquerque)
-v6.4.3
+v 6.4.3
- Don't use unicorn worker killer if PhusionPassenger is defined
-v6.4.2
+v 6.4.2
- Fixed wrong behaviour of script/upgrade.rb
-v6.4.1
+v 6.4.1
- Fixed bug with repository rename
- Fixed bug with project transfer
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index fd2a01863fd..944880fa15e 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-3.1.0
+3.2.0
diff --git a/Gemfile b/Gemfile
index 2c9fa2a0538..5c43015e52c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,4 +1,4 @@
-source "https://rubygems.org"
+source 'https://rubygems.org'
gem 'rails', '4.2.6'
gem 'rails-deprecated_sanitizer', '~> 1.0.3'
@@ -11,15 +11,15 @@ gem 'responders', '~> 2.0'
gem 'sprockets', '~> 3.6.0'
# Default values for AR models
-gem "default_value_for", "~> 3.0.0"
+gem 'default_value_for', '~> 3.0.0'
# Supported DBs
-gem "mysql2", '~> 0.3.16', group: :mysql
-gem "pg", '~> 0.18.2', group: :postgres
+gem 'mysql2', '~> 0.3.16', group: :mysql
+gem 'pg', '~> 0.18.2', group: :postgres
# Authentication libraries
gem 'devise', '~> 4.0'
-gem 'doorkeeper', '~> 3.1'
+gem 'doorkeeper', '~> 4.0'
gem 'omniauth', '~> 1.3.1'
gem 'omniauth-auth0', '~> 1.4.1'
gem 'omniauth-azure-oauth2', '~> 0.0.6'
@@ -28,7 +28,7 @@ gem 'omniauth-cas3', '~> 1.1.2'
gem 'omniauth-facebook', '~> 3.0.0'
gem 'omniauth-github', '~> 1.1.1'
gem 'omniauth-gitlab', '~> 1.0.0'
-gem 'omniauth-google-oauth2', '~> 0.2.0'
+gem 'omniauth-google-oauth2', '~> 0.4.1'
gem 'omniauth-kerberos', '~> 0.3.0', group: :kerberos
gem 'omniauth-saml', '~> 1.6.0'
gem 'omniauth-shibboleth', '~> 1.2.0'
@@ -48,16 +48,16 @@ gem 'attr_encrypted', '~> 3.0.0'
gem 'u2f', '~> 0.2.1'
# Browser detection
-gem "browser", '~> 2.2'
+gem 'browser', '~> 2.2'
# Extracting information from a git repository
# Provide access to Gitlab::Git library
-gem "gitlab_git", '~> 10.2'
+gem 'gitlab_git', '~> 10.2'
# LDAP Auth
# GitLab fork with several improvements to original library. For full list of changes
# see https://github.com/intridea/omniauth-ldap/compare/master...gitlabhq:master
-gem 'gitlab_omniauth-ldap', '~> 1.2.1', require: "omniauth-ldap"
+gem 'gitlab_omniauth-ldap', '~> 1.2.1', require: 'omniauth-ldap'
# Git Wiki
# Required manually in config/initializers/gollum.rb to control load order
@@ -65,7 +65,7 @@ gem 'gollum-lib', '~> 4.1.0', require: false
gem 'gollum-rugged_adapter', '~> 0.4.2', require: false
# Language detection
-gem "github-linguist", "~> 4.7.0", require: "linguist"
+gem 'github-linguist', '~> 4.7.0', require: 'linguist'
# API
gem 'grape', '~> 0.13.0'
@@ -73,13 +73,13 @@ gem 'grape-entity', '~> 0.4.2'
gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
# Pagination
-gem "kaminari", "~> 0.17.0"
+gem 'kaminari', '~> 0.17.0'
# HAML
gem 'hamlit', '~> 2.5'
# Files attachments
-gem "carrierwave", '~> 0.10.0'
+gem 'carrierwave', '~> 0.10.0'
# Drag and Drop UI
gem 'dropzonejs-rails', '~> 0.7.1'
@@ -94,13 +94,13 @@ gem 'fog-openstack', '~> 0.1'
gem 'fog-rackspace', '~> 0.1.1'
# for aws storage
-gem "unf", '~> 0.1.4'
+gem 'unf', '~> 0.1.4'
# Authorization
-gem "six", '~> 0.2.0'
+gem 'six', '~> 0.2.0'
# Seed data
-gem "seed-fu", '~> 2.3.5'
+gem 'seed-fu', '~> 2.3.5'
# Markdown and HTML processing
gem 'html-pipeline', '~> 1.11.0'
@@ -124,29 +124,29 @@ gem 'diffy', '~> 3.0.3'
# Application server
group :unicorn do
- gem "unicorn", '~> 4.9.0'
+ gem 'unicorn', '~> 4.9.0'
gem 'unicorn-worker-killer', '~> 0.4.2'
end
# State machine
-gem "state_machines-activerecord", '~> 0.4.0'
+gem 'state_machines-activerecord', '~> 0.4.0'
# Run events after state machine commits
-gem 'after_commit_queue'
+gem 'after_commit_queue', '~> 1.3.0'
# Issue tags
gem 'acts-as-taggable-on', '~> 3.4'
# Background jobs
-gem 'sinatra', '~> 1.4.4', require: nil
+gem 'sinatra', '~> 1.4.4', require: false
gem 'sidekiq', '~> 4.0'
gem 'sidekiq-cron', '~> 0.4.0'
-gem 'redis-namespace'
+gem 'redis-namespace', '~> 1.5.2'
# HTTP requests
-gem "httparty", '~> 0.13.3'
+gem 'httparty', '~> 0.13.3'
# Colored output to console
-gem "rainbow", '~> 2.1.0'
+gem 'rainbow', '~> 2.1.0'
# GitLab settings
gem 'settingslogic', '~> 2.0.9'
@@ -156,7 +156,7 @@ gem 'settingslogic', '~> 2.0.9'
gem 'version_sorter', '~> 2.0.0'
# Cache
-gem "redis-rails", '~> 4.0.0'
+gem 'redis-rails', '~> 4.0.0'
# Redis
gem 'redis', '~> 3.2'
@@ -169,13 +169,13 @@ gem 'tinder', '~> 1.10.0'
gem 'hipchat', '~> 1.5.0'
# Flowdock integration
-gem "gitlab-flowdock-git-hook", "~> 1.0.1"
+gem 'gitlab-flowdock-git-hook', '~> 1.0.1'
# Gemnasium integration
-gem "gemnasium-gitlab-service", "~> 0.2"
+gem 'gemnasium-gitlab-service', '~> 0.2'
# Slack integration
-gem "slack-notifier", "~> 1.2.0"
+gem 'slack-notifier', '~> 1.2.0'
# Asana integration
gem 'asana', '~> 0.4.0'
@@ -187,20 +187,20 @@ gem 'ruby-fogbugz', '~> 0.2.1'
gem 'd3_rails', '~> 3.5.0'
# underscore-rails
-gem "underscore-rails", "~> 1.8.0"
+gem 'underscore-rails', '~> 1.8.0'
# Sanitize user input
-gem "sanitize", '~> 2.0'
+gem 'sanitize', '~> 2.0'
gem 'babosa', '~> 1.0.2'
# Sanitizes SVG input
-gem "loofah", "~> 2.0.3"
+gem 'loofah', '~> 2.0.3'
# Working with license
gem 'licensee', '~> 8.0.0'
# Protect against bruteforcing
-gem "rack-attack", '~> 4.3.1'
+gem 'rack-attack', '~> 4.3.1'
# Ace editor
gem 'ace-rails-ap', '~> 4.0.2'
@@ -214,16 +214,16 @@ gem 'charlock_holmes', '~> 0.7.3'
# Parse duration
gem 'chronic_duration', '~> 0.10.6'
-gem "sass-rails", '~> 5.0.0'
-gem "coffee-rails", '~> 4.1.0'
-gem "uglifier", '~> 2.7.2'
+gem 'sass-rails', '~> 5.0.0'
+gem 'coffee-rails', '~> 4.1.0'
+gem 'uglifier', '~> 2.7.2'
gem 'turbolinks', '~> 2.5.0'
gem 'jquery-turbolinks', '~> 2.1.0'
gem 'addressable', '~> 2.3.8'
gem 'bootstrap-sass', '~> 3.3.0'
gem 'font-awesome-rails', '~> 4.6.1'
-gem 'gitlab_emoji', '~> 0.3.0'
+gem 'gemojione', '~> 2.6'
gem 'gon', '~> 6.0.1'
gem 'jquery-atwho-rails', '~> 1.3.2'
gem 'jquery-rails', '~> 4.1.0'
@@ -247,13 +247,13 @@ group :metrics do
end
group :development do
- gem "foreman"
+ gem 'foreman', '~> 0.78.0'
gem 'brakeman', '~> 3.3.0', require: false
gem 'letter_opener_web', '~> 1.3.0'
gem 'rerun', '~> 0.11.0'
- gem 'bullet', require: false
- gem 'rblineprof', platform: :mri, require: false
+ gem 'bullet', '~> 5.0.0', require: false
+ gem 'rblineprof', '~> 0.3.6', platform: :mri, require: false
gem 'web-console', '~> 2.0'
# Better errors handler
@@ -261,15 +261,15 @@ group :development do
gem 'binding_of_caller', '~> 0.7.2'
# Docs generator
- gem "sdoc", '~> 0.3.20'
+ gem 'sdoc', '~> 0.3.20'
# thin instead webrick
gem 'thin', '~> 1.7.0'
end
group :development, :test do
- gem 'byebug', platform: :mri
- gem 'pry-rails'
+ gem 'byebug', '~> 8.2.1', platform: :mri
+ gem 'pry-rails', '~> 0.3.4'
gem 'awesome_print', '~> 1.2.0', require: false
gem 'fuubar', '~> 2.0.0'
@@ -277,7 +277,7 @@ group :development, :test do
gem 'database_cleaner', '~> 1.4.0'
gem 'factory_girl_rails', '~> 4.6.0'
gem 'rspec-rails', '~> 3.5.0'
- gem 'rspec-retry'
+ gem 'rspec-retry', '~> 0.4.5'
gem 'spinach-rails', '~> 0.2.1'
gem 'spinach-rerun-reporter', '~> 0.0.2'
@@ -303,14 +303,14 @@ group :development, :test do
gem 'rubocop-rspec', '~> 1.5.0', require: false
gem 'scss_lint', '~> 0.47.0', require: false
gem 'simplecov', '~> 0.11.0', require: false
- gem 'flog', require: false
- gem 'flay', require: false
- gem 'bundler-audit', require: false
+ gem 'flog', '~> 4.3.2', require: false
+ gem 'flay', '~> 2.6.1', require: false
+ gem 'bundler-audit', '~> 0.5.0', require: false
- gem 'benchmark-ips', require: false
+ gem 'benchmark-ips', '~> 2.3.0', require: false
- gem "license_finder", require: false
- gem 'knapsack'
+ gem 'license_finder', '~> 2.1.0', require: false
+ gem 'knapsack', '~> 1.11.0'
end
group :test do
@@ -318,33 +318,33 @@ group :test do
gem 'email_spec', '~> 1.6.0'
gem 'webmock', '~> 1.21.0'
gem 'test_after_commit', '~> 0.4.2'
- gem 'sham_rack'
+ gem 'sham_rack', '~> 1.3.6'
end
group :production do
- gem "gitlab_meta", '7.0'
+ gem 'gitlab_meta', '7.0'
end
-gem "newrelic_rpm", '~> 3.14'
+gem 'newrelic_rpm', '~> 3.14'
gem 'octokit', '~> 4.3.0'
-gem "mail_room", "~> 0.8"
+gem 'mail_room', '~> 0.8'
gem 'email_reply_parser', '~> 0.5.8'
## CI
gem 'activerecord-session_store', '~> 1.0.0'
-gem "nested_form", '~> 0.3.2'
+gem 'nested_form', '~> 0.3.2'
# OAuth
-gem 'oauth2', '~> 1.0.0'
+gem 'oauth2', '~> 1.2.0'
# Soft deletion
-gem "paranoia", "~> 2.0"
+gem 'paranoia', '~> 2.0'
# Health check
-gem 'health_check', '~> 1.5.1'
+gem 'health_check', '~> 2.1.0'
# System information
gem 'vmstat', '~> 2.1.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index 9b07c97b078..f8018e58a5e 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -171,8 +171,8 @@ GEM
diff-lcs (1.2.5)
diffy (3.0.7)
docile (1.1.5)
- doorkeeper (3.1.0)
- railties (>= 3.2)
+ doorkeeper (4.0.0)
+ railties (>= 4.2)
dropzonejs-rails (0.7.2)
rails (> 3.1)
email_reply_parser (0.5.8)
@@ -255,7 +255,7 @@ GEM
ruby-progressbar (~> 1.4)
gemnasium-gitlab-service (0.2.6)
rugged (~> 0.21)
- gemojione (2.2.1)
+ gemojione (2.6.1)
json
get_process_mem (0.2.0)
gherkin-ruby (0.3.2)
@@ -274,8 +274,6 @@ GEM
diff-lcs (~> 1.1)
mime-types (>= 1.16, < 3)
posix-spawn (~> 0.3)
- gitlab_emoji (0.3.1)
- gemojione (~> 2.2, >= 2.2.1)
gitlab_git (10.2.3)
activesupport (~> 4.0)
charlock_holmes (~> 0.7.3)
@@ -324,8 +322,8 @@ GEM
thor
tilt
hashie (3.4.3)
- health_check (1.5.1)
- rails (>= 2.3.0)
+ health_check (2.1.0)
+ rails (>= 4.0)
hipchat (1.5.2)
httparty
mimemagic
@@ -355,7 +353,7 @@ GEM
jquery-ui-rails (5.0.5)
railties (>= 3.2.16)
json (1.8.3)
- jwt (1.5.2)
+ jwt (1.5.4)
kaminari (0.17.0)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
@@ -395,7 +393,7 @@ GEM
mini_portile2 (2.1.0)
minitest (5.7.0)
mousetrap-rails (1.4.6)
- multi_json (1.11.2)
+ multi_json (1.12.1)
multi_xml (0.5.5)
multipart-post (2.0.0)
mysql2 (0.3.20)
@@ -408,12 +406,12 @@ GEM
pkg-config (~> 1.1.7)
numerizer (0.1.1)
oauth (0.4.7)
- oauth2 (1.0.0)
+ oauth2 (1.2.0)
faraday (>= 0.8, < 0.10)
jwt (~> 1.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
- rack (~> 1.2)
+ rack (>= 1.2, < 3)
octokit (4.3.0)
sawyer (~> 0.7.0, >= 0.5.3)
omniauth (1.3.1)
@@ -441,7 +439,7 @@ GEM
omniauth-gitlab (1.0.1)
omniauth (~> 1.0)
omniauth-oauth2 (~> 1.0)
- omniauth-google-oauth2 (0.2.10)
+ omniauth-google-oauth2 (0.4.1)
addressable (~> 2.3)
jwt (~> 1.0)
multi_json (~> 1.3)
@@ -578,7 +576,7 @@ GEM
listen (~> 3.0)
responders (2.1.1)
railties (>= 4.2.0, < 5.1)
- rinku (1.7.3)
+ rinku (2.0.0)
rotp (2.1.2)
rouge (1.11.0)
rqrcode (0.7.0)
@@ -808,7 +806,7 @@ DEPENDENCIES
activerecord-session_store (~> 1.0.0)
acts-as-taggable-on (~> 3.4)
addressable (~> 2.3.8)
- after_commit_queue
+ after_commit_queue (~> 1.3.0)
akismet (~> 2.0)
allocations (~> 1.0)
asana (~> 0.4.0)
@@ -817,15 +815,15 @@ DEPENDENCIES
awesome_print (~> 1.2.0)
babosa (~> 1.0.2)
base32 (~> 0.3.0)
- benchmark-ips
+ benchmark-ips (~> 2.3.0)
better_errors (~> 1.0.1)
binding_of_caller (~> 0.7.2)
bootstrap-sass (~> 3.3.0)
brakeman (~> 3.3.0)
browser (~> 2.2)
- bullet
- bundler-audit
- byebug
+ bullet (~> 5.0.0)
+ bundler-audit (~> 0.5.0)
+ byebug (~> 8.2.1)
capybara (~> 2.6.2)
capybara-screenshot (~> 1.0.0)
carrierwave (~> 0.10.0)
@@ -840,14 +838,14 @@ DEPENDENCIES
devise (~> 4.0)
devise-two-factor (~> 3.0.0)
diffy (~> 3.0.3)
- doorkeeper (~> 3.1)
+ doorkeeper (~> 4.0)
dropzonejs-rails (~> 0.7.1)
email_reply_parser (~> 0.5.8)
email_spec (~> 1.6.0)
factory_girl_rails (~> 4.6.0)
ffaker (~> 2.0.0)
- flay
- flog
+ flay (~> 2.6.1)
+ flog (~> 4.3.2)
fog-aws (~> 0.9)
fog-azure (~> 0.0)
fog-core (~> 1.40)
@@ -856,13 +854,13 @@ DEPENDENCIES
fog-openstack (~> 0.1)
fog-rackspace (~> 0.1.1)
font-awesome-rails (~> 4.6.1)
- foreman
+ foreman (~> 0.78.0)
fuubar (~> 2.0.0)
gemnasium-gitlab-service (~> 0.2)
+ gemojione (~> 2.6)
github-linguist (~> 4.7.0)
github-markup (~> 1.3.1)
gitlab-flowdock-git-hook (~> 1.0.1)
- gitlab_emoji (~> 0.3.0)
gitlab_git (~> 10.2)
gitlab_meta (= 7.0)
gitlab_omniauth-ldap (~> 1.2.1)
@@ -872,7 +870,7 @@ DEPENDENCIES
grape (~> 0.13.0)
grape-entity (~> 0.4.2)
hamlit (~> 2.5)
- health_check (~> 1.5.1)
+ health_check (~> 2.1.0)
hipchat (~> 1.5.0)
html-pipeline (~> 1.11.0)
httparty (~> 0.13.3)
@@ -883,9 +881,9 @@ DEPENDENCIES
jquery-ui-rails (~> 5.0.0)
jwt
kaminari (~> 0.17.0)
- knapsack
+ knapsack (~> 1.11.0)
letter_opener_web (~> 1.3.0)
- license_finder
+ license_finder (~> 2.1.0)
licensee (~> 8.0.0)
loofah (~> 2.0.3)
mail_room (~> 0.8)
@@ -897,7 +895,7 @@ DEPENDENCIES
net-ssh (~> 3.0.1)
newrelic_rpm (~> 3.14)
nokogiri (~> 1.6.7, >= 1.6.7.2)
- oauth2 (~> 1.0.0)
+ oauth2 (~> 1.2.0)
octokit (~> 4.3.0)
omniauth (~> 1.3.1)
omniauth-auth0 (~> 1.4.1)
@@ -907,7 +905,7 @@ DEPENDENCIES
omniauth-facebook (~> 3.0.0)
omniauth-github (~> 1.1.1)
omniauth-gitlab (~> 1.0.0)
- omniauth-google-oauth2 (~> 0.2.0)
+ omniauth-google-oauth2 (~> 0.4.1)
omniauth-kerberos (~> 0.3.0)
omniauth-saml (~> 1.6.0)
omniauth-shibboleth (~> 1.2.0)
@@ -918,19 +916,19 @@ DEPENDENCIES
pg (~> 0.18.2)
poltergeist (~> 1.9.0)
premailer-rails (~> 1.9.0)
- pry-rails
+ pry-rails (~> 0.3.4)
rack-attack (~> 4.3.1)
rack-cors (~> 0.4.0)
rack-oauth2 (~> 1.2.1)
rails (= 4.2.6)
rails-deprecated_sanitizer (~> 1.0.3)
rainbow (~> 2.1.0)
- rblineprof
+ rblineprof (~> 0.3.6)
rdoc (~> 3.6)
recaptcha (~> 3.0)
redcarpet (~> 3.3.3)
redis (~> 3.2)
- redis-namespace
+ redis-namespace (~> 1.5.2)
redis-rails (~> 4.0.0)
request_store (~> 1.3.0)
rerun (~> 0.11.0)
@@ -938,7 +936,7 @@ DEPENDENCIES
rouge (~> 1.11)
rqrcode-rails3 (~> 0.1.7)
rspec-rails (~> 3.5.0)
- rspec-retry
+ rspec-retry (~> 0.4.5)
rubocop (~> 0.40.0)
rubocop-rspec (~> 1.5.0)
ruby-fogbugz (~> 0.2.1)
@@ -950,7 +948,7 @@ DEPENDENCIES
select2-rails (~> 3.5.9)
sentry-raven (~> 1.1.0)
settingslogic (~> 2.0.9)
- sham_rack
+ sham_rack (~> 1.3.6)
shoulda-matchers (~> 2.8.0)
sidekiq (~> 4.0)
sidekiq-cron (~> 0.4.0)
diff --git a/app/assets/images/emoji.png b/app/assets/images/emoji.png
index 99093d4725a..6bacb0e92b6 100644
--- a/app/assets/images/emoji.png
+++ b/app/assets/images/emoji.png
Binary files differ
diff --git a/app/assets/images/emoji@2x.png b/app/assets/images/emoji@2x.png
index 48989942a9f..99588b56616 100644
--- a/app/assets/images/emoji@2x.png
+++ b/app/assets/images/emoji@2x.png
Binary files differ
diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee
index 20fe5a5cc27..c98763d6271 100644
--- a/app/assets/javascripts/application.js.coffee
+++ b/app/assets/javascripts/application.js.coffee
@@ -47,14 +47,12 @@
#= require date.format
#= require_directory ./behaviors
#= require_directory ./blob
-#= require_directory ./ci
#= require_directory ./commit
#= require_directory ./extensions
#= require_directory ./lib/utils
#= require_directory ./u2f
#= require_directory .
#= require fuzzaldrin-plus
-#= require cropper
#= require u2f
window.slugify = (text) ->
diff --git a/app/assets/javascripts/ci/build.coffee b/app/assets/javascripts/build.coffee
index 2d515d7efa2..cf203ea43a0 100644
--- a/app/assets/javascripts/ci/build.coffee
+++ b/app/assets/javascripts/build.coffee
@@ -1,9 +1,9 @@
-class @CiBuild
+class @Build
@interval: null
@state: null
- constructor: (@build_url, @build_status, @state) ->
- clearInterval(CiBuild.interval)
+ constructor: (@page_url, @build_url, @build_status, @state) ->
+ clearInterval(Build.interval)
# Init breakpoint checker
@bp = Breakpoints.get()
@@ -40,8 +40,8 @@ class @CiBuild
# Check for new build output if user still watching build page
# Only valid for runnig build when output changes during time
#
- CiBuild.interval = setInterval =>
- if window.location.href.split("#").first() is @build_url
+ Build.interval = setInterval =>
+ if window.location.href.split("#").first() is @page_url
@getBuildTrace()
, 4000
@@ -57,7 +57,7 @@ class @CiBuild
getBuildTrace: ->
$.ajax
- url: "#{@build_url}/trace.json?state=#{encodeURIComponent(@state)}"
+ url: "#{@page_url}/trace.json?state=#{encodeURIComponent(@state)}"
dataType: "json"
success: (log) =>
if log.state
@@ -70,7 +70,7 @@ class @CiBuild
$('.js-build-output').html log.html
@checkAutoscroll()
else if log.status isnt @build_status
- Turbolinks.visit @build_url
+ Turbolinks.visit @page_url
checkAutoscroll: ->
$("html,body").scrollTop $("#build-trace").height() if "enabled" is $("#autoscroll-button").data("state")
diff --git a/app/assets/javascripts/ci/application.js.coffee b/app/assets/javascripts/ci/application.js.coffee
deleted file mode 100644
index ca24c1d759f..00000000000
--- a/app/assets/javascripts/ci/application.js.coffee
+++ /dev/null
@@ -1,12 +0,0 @@
-#= require pager
-#= require jquery_nested_form
-#= require_tree .
-
-$(document).on 'click', '.assign-all-runner', ->
- $(this).replaceWith('<i class="fa fa-refresh fa-spin"></i> Assign in progress..')
-
-window.unbindEvents = ->
- $(document).unbind('scroll')
- $(document).off('scroll')
-
-document.addEventListener("page:fetch", unbindEvents)
diff --git a/app/assets/javascripts/ci/projects.js.coffee b/app/assets/javascripts/ci/projects.js.coffee
deleted file mode 100644
index e6406011d11..00000000000
--- a/app/assets/javascripts/ci/projects.js.coffee
+++ /dev/null
@@ -1,3 +0,0 @@
-$(document).on 'click', '.badge-codes-toggle', ->
- $('.badge-codes-block').toggleClass("hide")
- return false
diff --git a/app/assets/javascripts/diff.js.coffee b/app/assets/javascripts/diff.js.coffee
index 6d9b364cb8d..c132cc8c542 100644
--- a/app/assets/javascripts/diff.js.coffee
+++ b/app/assets/javascripts/diff.js.coffee
@@ -1,6 +1,9 @@
class @Diff
UNFOLD_COUNT = 20
constructor: ->
+ $('.files .diff-file').singleFileDiff()
+ @filesCommentButton = $('.files .diff-file').filesCommentButton()
+
$(document).off('click', '.js-unfold')
$(document).on('click', '.js-unfold', (event) =>
target = $(event.target)
@@ -36,7 +39,7 @@ class @Diff
# see https://gitlab.com/gitlab-org/gitlab-ce/issues/707
indent: 1
- $.get(link, params, (response) =>
+ $.get(link, params, (response) ->
target.parent().replaceWith(response)
)
)
diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee
index 9493a575801..74fd77cf7ab 100644
--- a/app/assets/javascripts/dispatcher.js.coffee
+++ b/app/assets/javascripts/dispatcher.js.coffee
@@ -127,11 +127,10 @@ class Dispatcher
when 'groups'
new UsersSelect()
when 'projects'
- new NamespaceSelect()
+ new NamespaceSelects()
when 'dashboard', 'root'
shortcut_handler = new ShortcutsDashboardNavigation()
when 'profiles'
- new Profile()
new NotificationsForm()
new NotificationsDropdown()
when 'projects'
diff --git a/app/assets/javascripts/dropzone_input.js.coffee b/app/assets/javascripts/dropzone_input.js.coffee
index e2194589b38..665246e2a7d 100644
--- a/app/assets/javascripts/dropzone_input.js.coffee
+++ b/app/assets/javascripts/dropzone_input.js.coffee
@@ -70,12 +70,12 @@ class @DropzoneInput
pasteText response.link.markdown
return
- error: (temp, errorMessage) ->
+ error: (temp) ->
errorAlert = $(form).find('.error-alert')
checkIfMsgExists = errorAlert.children().length
if checkIfMsgExists is 0
errorAlert.append divAlert
- $(".div-dropzone-alert").append btnAlert + errorMessage
+ $(".div-dropzone-alert").append "#{btnAlert}Attaching the file failed."
return
totaluploadprogress: (totalUploadProgress) ->
diff --git a/app/assets/javascripts/files_comment_button.js.coffee b/app/assets/javascripts/files_comment_button.js.coffee
new file mode 100644
index 00000000000..db0bf7082a9
--- /dev/null
+++ b/app/assets/javascripts/files_comment_button.js.coffee
@@ -0,0 +1,97 @@
+class @FilesCommentButton
+ COMMENT_BUTTON_CLASS = '.add-diff-note'
+ COMMENT_BUTTON_TEMPLATE = _.template '<button name="button" type="submit" class="btn <%- COMMENT_BUTTON_CLASS %> js-add-diff-note-button" title="Add a comment to this line"><i class="fa fa-comment-o"></i></button>'
+ LINE_HOLDER_CLASS = '.line_holder'
+ LINE_NUMBER_CLASS = 'diff-line-num'
+ LINE_CONTENT_CLASS = 'line_content'
+ UNFOLDABLE_LINE_CLASS = 'js-unfold'
+ EMPTY_CELL_CLASS = 'empty-cell'
+ OLD_LINE_CLASS = 'old_line'
+ NEW_CLASS = 'new'
+ LINE_COLUMN_CLASSES = ".#{LINE_NUMBER_CLASS}, .line_content"
+ TEXT_FILE_SELECTOR = '.text-file'
+ DEBOUNCE_TIMEOUT_DURATION = 100
+
+ constructor: (@filesContainerElement) ->
+ @VIEW_TYPE = $('input#view[type=hidden]').val()
+
+ debounce = _.debounce @render, DEBOUNCE_TIMEOUT_DURATION
+
+ $(document)
+ .on 'mouseover', LINE_COLUMN_CLASSES, debounce
+ .on 'mouseleave', LINE_COLUMN_CLASSES, @destroy
+
+ render: (e) =>
+ $currentTarget = $(e.currentTarget)
+ buttonParentElement = @getButtonParent $currentTarget
+ return unless @shouldRender e, buttonParentElement
+
+ textFileElement = @getTextFileElement $currentTarget
+ lineContentElement = @getLineContent $currentTarget
+
+ buttonParentElement.append @buildButton
+ noteableType: textFileElement.attr 'data-noteable-type'
+ noteableID: textFileElement.attr 'data-noteable-id'
+ commitID: textFileElement.attr 'data-commit-id'
+ noteType: lineContentElement.attr 'data-note-type'
+ position: lineContentElement.attr 'data-position'
+ lineType: lineContentElement.attr 'data-line-type'
+ discussionID: lineContentElement.attr 'data-discussion-id'
+ lineCode: lineContentElement.attr 'data-line-code'
+ return
+
+ destroy: (e) =>
+ return if @isMovingToSameType e
+ $(COMMENT_BUTTON_CLASS, @getButtonParent $(e.currentTarget)).remove()
+ return
+
+ buildButton: (buttonAttributes) ->
+ initializedButtonTemplate = COMMENT_BUTTON_TEMPLATE
+ COMMENT_BUTTON_CLASS: COMMENT_BUTTON_CLASS.substr 1
+ $(initializedButtonTemplate).attr
+ 'data-noteable-type': buttonAttributes.noteableType
+ 'data-noteable-id': buttonAttributes.noteableID
+ 'data-commit-id': buttonAttributes.commitID
+ 'data-note-type': buttonAttributes.noteType
+ 'data-line-code': buttonAttributes.lineCode
+ 'data-position': buttonAttributes.position
+ 'data-discussion-id': buttonAttributes.discussionID
+ 'data-line-type': buttonAttributes.lineType
+
+ getTextFileElement: (hoveredElement) ->
+ $(hoveredElement.closest TEXT_FILE_SELECTOR)
+
+ getLineContent: (hoveredElement) ->
+ return hoveredElement if hoveredElement.hasClass LINE_CONTENT_CLASS
+
+ $(".#{LINE_CONTENT_CLASS + @diffTypeClass hoveredElement}", hoveredElement.parent())
+
+ getButtonParent: (hoveredElement) ->
+ if @VIEW_TYPE is 'inline'
+ return hoveredElement if hoveredElement.hasClass OLD_LINE_CLASS
+
+ $(".#{OLD_LINE_CLASS}", hoveredElement.parent())
+ else
+ return hoveredElement if hoveredElement.hasClass LINE_NUMBER_CLASS
+
+ $(".#{LINE_NUMBER_CLASS + @diffTypeClass hoveredElement}", hoveredElement.parent())
+
+ diffTypeClass: (hoveredElement) ->
+ if hoveredElement.hasClass(NEW_CLASS) then '.new' else '.old'
+
+ isMovingToSameType: (e) ->
+ newButtonParent = @getButtonParent $(e.toElement)
+ return false unless newButtonParent
+ newButtonParent.is @getButtonParent $(e.currentTarget)
+
+ shouldRender: (e, buttonParentElement) ->
+ (not buttonParentElement.hasClass(EMPTY_CELL_CLASS) and \
+ not buttonParentElement.hasClass(UNFOLDABLE_LINE_CLASS) and \
+ $(COMMENT_BUTTON_CLASS, buttonParentElement).length is 0)
+
+$.fn.filesCommentButton = ->
+ return unless this and @parent().data('can-create-note')?
+
+ @each ->
+ unless $.data this, 'filesCommentButton'
+ $.data this, 'filesCommentButton', new FilesCommentButton $(this)
diff --git a/app/assets/javascripts/flash.js.coffee b/app/assets/javascripts/flash.js.coffee
index b76d214790a..5a493041538 100644
--- a/app/assets/javascripts/flash.js.coffee
+++ b/app/assets/javascripts/flash.js.coffee
@@ -1,24 +1,28 @@
class @Flash
- constructor: (message, type = 'alert')->
- @flash = $(".flash-container")
- @flash.html("")
+ hideFlash = -> $(@).fadeOut()
- innerDiv = $('<div/>',
+ constructor: (message, type = 'alert', parent = null)->
+ if parent
+ @flashContainer = parent.find('.flash-container')
+ else
+ @flashContainer = $('.flash-container-page')
+
+ @flashContainer.html('')
+
+ flash = $('<div/>',
class: "flash-#{type}"
)
- innerDiv.appendTo(".flash-container")
+ flash.on 'click', hideFlash
- textDiv = $("<div/>",
- class: "flash-text",
+ textDiv = $('<div/>',
+ class: 'flash-text',
text: message
)
- textDiv.appendTo(innerDiv)
+ textDiv.appendTo(flash)
- if @flash.parent().hasClass('content-wrapper')
+ if @flashContainer.parent().hasClass('content-wrapper')
textDiv.addClass('container-fluid container-limited')
- @flash.click -> $(@).fadeOut()
- @flash.show()
+ flash.appendTo(@flashContainer)
+ @flashContainer.show()
- pinTo: (selector) ->
- @flash.detach().appendTo(selector)
diff --git a/app/assets/javascripts/gfm_auto_complete.js.coffee b/app/assets/javascripts/gfm_auto_complete.js.coffee
index b7d040bae85..4a851d9c9fb 100644
--- a/app/assets/javascripts/gfm_auto_complete.js.coffee
+++ b/app/assets/javascripts/gfm_auto_complete.js.coffee
@@ -190,7 +190,7 @@ GitLab.GfmAutoComplete =
callbacks:
beforeSave: (merges) ->
sanitizeLabelTitle = (title)->
- if /\w+\s+\w+/g.test(title)
+ if /[\w\?&]+\s+[\w\?&]+/g.test(title)
"\"#{sanitize(title)}\""
else
sanitize(title)
diff --git a/app/assets/javascripts/gl_dropdown.js.coffee b/app/assets/javascripts/gl_dropdown.js.coffee
index ed9dfcc917e..1c65e833d47 100644
--- a/app/assets/javascripts/gl_dropdown.js.coffee
+++ b/app/assets/javascripts/gl_dropdown.js.coffee
@@ -56,6 +56,7 @@ class GitLabDropdownFilter
return BLUR_KEYCODES.indexOf(keyCode) >= 0
filter: (search_text) ->
+ @options.onFilter(search_text) if @options.onFilter
data = @options.data()
if data? and not @options.filterByText
@@ -195,6 +196,7 @@ class GitLabDropdown
@filter = new GitLabDropdownFilter @filterInput,
filterInputBlur: @filterInputBlur
filterByText: @options.filterByText
+ onFilter: @options.onFilter
remote: @options.filterRemote
query: @options.data
keys: searchFields
@@ -530,7 +532,7 @@ class GitLabDropdown
if $el.length
e.preventDefault()
e.stopImmediatePropagation()
- $(selector, @dropdown)[0].click()
+ $el.first().trigger('click')
addArrowKeyEvent: ->
ARROW_KEY_CODES = [38, 40]
diff --git a/app/assets/javascripts/issuable.js.coffee b/app/assets/javascripts/issuable.js.coffee
index 0527c66461c..c71d4ecf505 100644
--- a/app/assets/javascripts/issuable.js.coffee
+++ b/app/assets/javascripts/issuable.js.coffee
@@ -11,11 +11,11 @@ issuable_created = false
initTemplates: ->
Issuable.labelRow = _.template(
'<% _.each(labels, function(label){ %>
- <span class="label-row btn-group" role="group" aria-label="<%= _.escape(label.title) %>" style="color: <%= label.text_color %>;">
- <a href="#" class="btn btn-transparent has-tooltip" style="background-color: <%= label.color %>;" title="<%= _.escape(label.description) %>" data-container="body">
- <%= _.escape(label.title) %>
+ <span class="label-row btn-group" role="group" aria-label="<%- label.title %>" style="color: <%- label.text_color %>;">
+ <a href="#" class="btn btn-transparent has-tooltip" style="background-color: <%- label.color %>;" title="<%- label.description %>" data-container="body">
+ <%- label.title %>
</a>
- <button type="button" class="btn btn-transparent label-remove js-label-filter-remove" style="background-color: <%= label.color %>;" data-label="<%= _.escape(label.title) %>">
+ <button type="button" class="btn btn-transparent label-remove js-label-filter-remove" style="background-color: <%- label.color %>;" data-label="<%- label.title %>">
<i class="fa fa-times"></i>
</button>
</span>
diff --git a/app/assets/javascripts/labels_select.js.coffee b/app/assets/javascripts/labels_select.js.coffee
index e95fd96a83f..7688609b301 100644
--- a/app/assets/javascripts/labels_select.js.coffee
+++ b/app/assets/javascripts/labels_select.js.coffee
@@ -32,9 +32,9 @@ class @LabelsSelect
if issueUpdateURL
labelHTMLTemplate = _.template(
'<% _.each(labels, function(label){ %>
- <a href="<%= ["",issueURLSplit[1], issueURLSplit[2],""].join("/") %>issues?label_name[]=<%= _.escape(label.title) %>">
- <span class="label has-tooltip color-label" title="<%= _.escape(label.description) %>" style="background-color: <%= label.color %>; color: <%= label.text_color %>;">
- <%= _.escape(label.title) %>
+ <a href="<%- ["",issueURLSplit[1], issueURLSplit[2],""].join("/") %>issues?label_name[]=<%- encodeURIComponent(label.title) %>">
+ <span class="label has-tooltip color-label" title="<%- label.description %>" style="background-color: <%- label.color %>; color: <%- label.text_color %>;">
+ <%- label.title %>
</span>
</a>
<% }); %>'
@@ -261,7 +261,7 @@ class @LabelsSelect
$a.attr('data-label-id', label.id)
$a.addClass(selectedClass.join(' '))
- .html("#{colorEl} #{_.escape(label.title)}")
+ .html("#{colorEl} #{label.title}")
# Return generated html
$li.html($a).prop('outerHTML')
@@ -288,7 +288,7 @@ class @LabelsSelect
fieldName: $dropdown.data('field-name')
id: (label) ->
if $dropdown.hasClass("js-filter-submit") and not label.isAny?
- _.escape label.title
+ label.title
else
label.id
diff --git a/app/assets/javascripts/lib/cropper.js.coffee b/app/assets/javascripts/lib/cropper.js.coffee
new file mode 100644
index 00000000000..32536d23fe3
--- /dev/null
+++ b/app/assets/javascripts/lib/cropper.js.coffee
@@ -0,0 +1 @@
+#= require cropper
diff --git a/app/assets/javascripts/lib/utils/common_utils.js.coffee b/app/assets/javascripts/lib/utils/common_utils.js.coffee
index e39dcb2daa9..d4dd3dc329a 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js.coffee
+++ b/app/assets/javascripts/lib/utils/common_utils.js.coffee
@@ -5,12 +5,12 @@
w.gl.utils.isInGroupsPage = ->
- return $('body').data('page').split(':')[0] is 'groups'
+ return gl.utils.getPagePath() is 'groups'
w.gl.utils.isInProjectPage = ->
- return $('body').data('page').split(':')[0] is 'projects'
+ return gl.utils.getPagePath() is 'projects'
w.gl.utils.getProjectSlug = ->
@@ -40,6 +40,9 @@
e.stopImmediatePropagation()
return false
+ gl.utils.getPagePath = ->
+ return $('body').data('page').split(':')[0]
+
jQuery.timefor = (time, suffix, expiredLabel) ->
diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js.coffee b/app/assets/javascripts/lib/utils/datetime_utility.js.coffee
index 948d6dbf07e..178963fe0aa 100644
--- a/app/assets/javascripts/lib/utils/datetime_utility.js.coffee
+++ b/app/assets/javascripts/lib/utils/datetime_utility.js.coffee
@@ -2,10 +2,14 @@
w.gl ?= {}
w.gl.utils ?= {}
+ w.gl.utils.days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
w.gl.utils.formatDate = (datetime) ->
dateFormat(datetime, 'mmm d, yyyy h:MMtt Z')
+ w.gl.utils.getDayName = (date) ->
+ this.days[date.getDay()]
+
w.gl.utils.localTimeAgo = ($timeagoEls, setTimeago = true) ->
$timeagoEls.each( ->
$el = $(@)
diff --git a/app/assets/javascripts/lib/utils/text_utility.js.coffee b/app/assets/javascripts/lib/utils/text_utility.js.coffee
index 7bcb876d056..2e1407f8738 100644
--- a/app/assets/javascripts/lib/utils/text_utility.js.coffee
+++ b/app/assets/javascripts/lib/utils/text_utility.js.coffee
@@ -49,8 +49,9 @@
insertText = "#{startChar}#{tag}#{selected}#{if wrap then tag else ' '}"
if document.queryCommandSupported('insertText')
- document.execCommand 'insertText', false, insertText
- else
+ inserted = document.execCommand 'insertText', false, insertText
+
+ unless inserted
try
document.execCommand("ms-beginUndoUnit")
diff --git a/app/assets/javascripts/merge_request_tabs.js.coffee b/app/assets/javascripts/merge_request_tabs.js.coffee
index 894f80586f1..86539e0d725 100644
--- a/app/assets/javascripts/merge_request_tabs.js.coffee
+++ b/app/assets/javascripts/merge_request_tabs.js.coffee
@@ -153,17 +153,18 @@ class @MergeRequestTabs
loadDiff: (source) ->
return if @diffsLoaded
-
@_get
url: "#{source}.json" + @_location.search
success: (data) =>
$('#diffs').html data.html
gl.utils.localTimeAgo($('.js-timeago', 'div#diffs'))
$('#diffs .js-syntax-highlight').syntaxHighlight()
+ $('#diffs .diff-file').singleFileDiff()
@expandViewContainer() if @diffViewType() is 'parallel'
@diffsLoaded = true
@scrollToElement("#diffs")
@highlighSelectedLine()
+ @filesCommentButton = $('.files .diff-file').filesCommentButton()
$(document)
.off 'click', '.diff-line-num a'
diff --git a/app/assets/javascripts/milestone_select.js.coffee b/app/assets/javascripts/milestone_select.js.coffee
index 02480f3a025..8ab03ed93ee 100644
--- a/app/assets/javascripts/milestone_select.js.coffee
+++ b/app/assets/javascripts/milestone_select.js.coffee
@@ -24,14 +24,14 @@ class @MilestoneSelect
if issueUpdateURL
milestoneLinkTemplate = _.template(
- '<a href="/<%= namespace %>/<%= path %>/milestones/<%= iid %>" class="bold has-tooltip" data-container="body" title="<%= remaining %>"><%= _.escape(title) %></a>'
+ '<a href="/<%- namespace %>/<%- path %>/milestones/<%- iid %>" class="bold has-tooltip" data-container="body" title="<%- remaining %>"><%- title %></a>'
)
milestoneLinkNoneTemplate = '<span class="no-value">None</span>'
collapsedSidebarLabelTemplate = _.template(
- '<span class="has-tooltip" data-container="body" title="<%= remaining %>" data-placement="left">
- <%= _.escape(title) %>
+ '<span class="has-tooltip" data-container="body" title="<%- remaining %>" data-placement="left">
+ <%- title %>
</span>'
)
diff --git a/app/assets/javascripts/namespace_select.js.coffee b/app/assets/javascripts/namespace_select.js.coffee
index a02c4515ccc..3b419dff105 100644
--- a/app/assets/javascripts/namespace_select.js.coffee
+++ b/app/assets/javascripts/namespace_select.js.coffee
@@ -1,25 +1,56 @@
class @NamespaceSelect
- constructor: ->
- namespaceFormatResult = (namespace) ->
- markup = "<div class='namespace-result'>"
- markup += "<span class='namespace-kind'>" + namespace.kind + "</span>"
- markup += "<span class='namespace-path'>" + namespace.path + "</span>"
- markup += "</div>"
- markup
-
- formatSelection = (namespace) ->
- namespace.kind + ": " + namespace.path
-
- $('.ajax-namespace-select').each (i, select) ->
- $(select).select2
- placeholder: "Search for namespace"
- multiple: $(select).hasClass('multiselect')
- minimumInputLength: 0
- query: (query) ->
- Api.namespaces query.term, (namespaces) ->
- data = { results: namespaces }
- query.callback(data)
-
- dropdownCssClass: "ajax-namespace-dropdown"
- formatResult: namespaceFormatResult
- formatSelection: formatSelection
+ constructor: (opts) ->
+ {
+ @dropdown
+ } = opts
+
+ showAny = true
+ fieldName = 'namespace_id'
+
+ if @dropdown.attr 'data-field-name'
+ fieldName = @dropdown.data 'fieldName'
+
+ if @dropdown.attr 'data-show-any'
+ showAny = @dropdown.data 'showAny'
+
+ @dropdown.glDropdown(
+ filterable: true
+ selectable: true
+ filterRemote: true
+ search:
+ fields: ['path']
+ fieldName: fieldName
+ toggleLabel: (selected) ->
+ return if not selected.id? then selected.text else "#{selected.kind}: #{selected.path}"
+ data: (term, dataCallback) ->
+ Api.namespaces term, (namespaces) ->
+ if showAny
+ anyNamespace =
+ text: 'Any namespace'
+ id: null
+
+ namespaces.unshift(anyNamespace)
+ namespaces.splice 1, 0, 'divider'
+
+ dataCallback(namespaces)
+ text: (namespace) ->
+ return if not namespace.id? then namespace.text else "#{namespace.kind}: #{namespace.path}"
+ renderRow: @renderRow
+ clicked: @onSelectItem
+ )
+
+ onSelectItem: (item, el, e) =>
+ e.preventDefault()
+
+class @NamespaceSelects
+ constructor: (opts = {}) ->
+ {
+ @$dropdowns = $('.js-namespace-select')
+ } = opts
+
+ @$dropdowns.each (i, dropdown) ->
+ $dropdown = $(dropdown)
+
+ new NamespaceSelect(
+ dropdown: $dropdown
+ )
diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee
index 17f7e180127..0ea54faae1a 100644
--- a/app/assets/javascripts/notes.js.coffee
+++ b/app/assets/javascripts/notes.js.coffee
@@ -100,13 +100,40 @@ class @Notes
$('.note .js-task-list-container').taskList('disable')
$(document).off 'tasklist:changed', '.note .js-task-list-container'
- keydownNoteText: (e) ->
- $this = $(this)
- if $this.val() is '' and e.which is 38 and not isMetaKey e
- myLastNote = $("li.note[data-author-id='#{gon.current_user_id}'][data-editable]:last")
- if myLastNote.length
- myLastNoteEditBtn = myLastNote.find('.js-note-edit')
- myLastNoteEditBtn.trigger('click', [true, myLastNote])
+ keydownNoteText: (e) =>
+ return if isMetaKey e
+
+ $textarea = $(e.target)
+
+ # Edit previous note when UP arrow is hit
+ switch e.which
+ when 38
+ return unless $textarea.val() is ''
+
+ myLastNote = $("li.note[data-author-id='#{gon.current_user_id}'][data-editable]:last")
+ if myLastNote.length
+ myLastNoteEditBtn = myLastNote.find('.js-note-edit')
+ myLastNoteEditBtn.trigger('click', [true, myLastNote])
+
+ # Cancel creating diff note or editing any note when ESCAPE is hit
+ when 27
+ discussionNoteForm = $textarea.closest('.js-discussion-note-form')
+ if discussionNoteForm.length
+ if $textarea.val() isnt ''
+ return unless confirm('Are you sure you want to cancel creating this comment?')
+
+ @removeDiscussionNoteForm(discussionNoteForm)
+ return
+
+ editNote = $textarea.closest('.note')
+ if editNote.length
+ originalText = $textarea.closest('form').data('original-note')
+ newText = $textarea.val()
+ if originalText isnt newText
+ return unless confirm('Are you sure you want to cancel editing this comment?')
+
+ @removeNoteEditForm(editNote)
+
isMetaKey = (e) ->
(e.metaKey or e.ctrlKey or e.altKey or e.shiftKey)
@@ -167,8 +194,7 @@ class @Notes
renderNote: (note) ->
unless note.valid
if note.award
- flash = new Flash('You have already awarded this emoji!', 'alert')
- flash.pinTo('.header-content')
+ new Flash('You have already awarded this emoji!', 'alert')
return
if note.award
@@ -213,12 +239,16 @@ class @Notes
@note_ids.push(note.id)
form = $("#new-discussion-note-form-#{note.discussion_id}")
+ if note.original_discussion_id? and form.length is 0
+ form = $("#new-discussion-note-form-#{note.original_discussion_id}")
row = form.closest("tr")
note_html = $(note.html)
note_html.syntaxHighlight()
# is this the first note of discussion?
discussionContainer = $(".notes[data-discussion-id='" + note.discussion_id + "']")
+ if note.original_discussion_id? and discussionContainer.length is 0
+ discussionContainer = $(".notes[data-discussion-id='" + note.original_discussion_id + "']")
if discussionContainer.length is 0
# insert the note and the reply button after the temp row
row.after note.discussion_html
@@ -291,8 +321,11 @@ class @Notes
form.addClass "js-main-target-form"
form.find("#note_line_code").remove()
+ form.find("#note_position").remove()
form.find("#note_type").remove()
+ @parentTimeline = form.parents('.timeline')
+
###
General note form setup.
@@ -308,10 +341,12 @@ class @Notes
new Autosave textarea, [
"Note"
- form.find("#note_commit_id").val()
- form.find("#note_line_code").val()
form.find("#note_noteable_type").val()
form.find("#note_noteable_id").val()
+ form.find("#note_commit_id").val()
+ form.find("#note_type").val()
+ form.find("#note_line_code").val()
+ form.find("#note_position").val()
]
###
@@ -323,8 +358,7 @@ class @Notes
@renderNote(note)
addNoteError: (xhr, note, status) =>
- flash = new Flash('Your comment could not be submitted! Please check your network connection and try again.', 'alert')
- flash.pinTo('.md-area')
+ new Flash('Your comment could not be submitted! Please check your network connection and try again.', 'alert', @parentTimeline)
###
Called in response to the new note form being submitted
@@ -401,9 +435,12 @@ class @Notes
Hides edit form and restores the original note text to the editor textarea.
###
- cancelEdit: (e) ->
+ cancelEdit: (e) =>
e.preventDefault()
- note = $(this).closest(".note")
+ note = $(e.target).closest('.note')
+ @removeNoteEditForm(note)
+
+ removeNoteEditForm: (note) ->
form = note.find(".current-note-edit-form")
note.removeClass "is-editting"
form.removeClass("current-note-edit-form")
@@ -482,10 +519,12 @@ class @Notes
setupDiscussionNoteForm: (dataHolder, form) =>
# setup note target
form.attr 'id', "new-discussion-note-form-#{dataHolder.data("discussionId")}"
+ form.attr "data-line-code", dataHolder.data("lineCode")
form.find("#note_type").val dataHolder.data("noteType")
form.find("#line_type").val dataHolder.data("lineType")
form.find("#note_commit_id").val dataHolder.data("commitId")
form.find("#note_line_code").val dataHolder.data("lineCode")
+ form.find("#note_position").val dataHolder.attr("data-position")
form.find("#note_noteable_type").val dataHolder.data("noteableType")
form.find("#note_noteable_id").val dataHolder.data("noteableId")
form.find('.js-note-discard')
diff --git a/app/assets/javascripts/profile/application.js.coffee b/app/assets/javascripts/profile/application.js.coffee
new file mode 100644
index 00000000000..91cacfece46
--- /dev/null
+++ b/app/assets/javascripts/profile/application.js.coffee
@@ -0,0 +1,2 @@
+#
+#= require_tree .
diff --git a/app/assets/javascripts/gl_crop.js.coffee b/app/assets/javascripts/profile/gl_crop.js.coffee
index df9bfdfa6cc..df9bfdfa6cc 100644
--- a/app/assets/javascripts/gl_crop.js.coffee
+++ b/app/assets/javascripts/profile/gl_crop.js.coffee
diff --git a/app/assets/javascripts/profile.js.coffee b/app/assets/javascripts/profile/profile.js.coffee
index 1583d1ba6f9..f3b05f2c646 100644
--- a/app/assets/javascripts/profile.js.coffee
+++ b/app/assets/javascripts/profile/profile.js.coffee
@@ -78,3 +78,6 @@ $ ->
if comment && comment.length > 1 && $title.val() == ''
$title.val(comment[1]).change()
+
+ if gl.utils.getPagePath() == 'profiles'
+ new Profile()
diff --git a/app/assets/javascripts/protected_branch_select.js.coffee b/app/assets/javascripts/protected_branch_select.js.coffee
new file mode 100644
index 00000000000..6d45770ace9
--- /dev/null
+++ b/app/assets/javascripts/protected_branch_select.js.coffee
@@ -0,0 +1,40 @@
+class @ProtectedBranchSelect
+ constructor: (currentProject) ->
+ $('.dropdown-footer').hide();
+ @dropdown = $('.js-protected-branch-select').glDropdown(
+ data: @getProtectedBranches
+ filterable: true
+ remote: false
+ search:
+ fields: ['title']
+ selectable: true
+ toggleLabel: (selected) -> if (selected and 'id' of selected) then selected.title else 'Protected Branch'
+ fieldName: 'protected_branch[name]'
+ text: (protected_branch) -> _.escape(protected_branch.title)
+ id: (protected_branch) -> _.escape(protected_branch.id)
+ onFilter: @toggleCreateNewButton
+ clicked: () -> $('.protect-branch-btn').attr('disabled', false)
+ )
+
+ $('.create-new-protected-branch').on 'click', (event) =>
+ # Refresh the dropdown's data, which ends up calling `getProtectedBranches`
+ @dropdown.data('glDropdown').remote.execute()
+ @dropdown.data('glDropdown').selectRowAtIndex(event, 0)
+
+ getProtectedBranches: (term, callback) =>
+ if @selectedBranch
+ callback(gon.open_branches.concat(@selectedBranch))
+ else
+ callback(gon.open_branches)
+
+ toggleCreateNewButton: (branchName) =>
+ @selectedBranch = { title: branchName, id: branchName, text: branchName }
+
+ if branchName is ''
+ $('.protected-branch-select-footer-list').addClass('hidden')
+ $('.dropdown-footer').hide();
+ else
+ $('.create-new-protected-branch').text("Create Protected Branch: #{branchName}")
+ $('.protected-branch-select-footer-list').removeClass('hidden')
+ $('.dropdown-footer').show();
+
diff --git a/app/assets/javascripts/protected_branches.js.coffee b/app/assets/javascripts/protected_branches.js.coffee
index 5753c9d4e72..79c2306e4d2 100644
--- a/app/assets/javascripts/protected_branches.js.coffee
+++ b/app/assets/javascripts/protected_branches.js.coffee
@@ -11,7 +11,8 @@ $ ->
dataType: "json"
data:
id: id
- developers_can_push: checked
+ protected_branch:
+ developers_can_push: checked
success: ->
row = $(e.target)
diff --git a/app/assets/javascripts/single_file_diff.js.coffee b/app/assets/javascripts/single_file_diff.js.coffee
new file mode 100644
index 00000000000..f3e225c3728
--- /dev/null
+++ b/app/assets/javascripts/single_file_diff.js.coffee
@@ -0,0 +1,54 @@
+class @SingleFileDiff
+
+ WRAPPER = '<div class="diff-content diff-wrap-lines"></div>'
+ LOADING_HTML = '<i class="fa fa-spinner fa-spin"></i>'
+ ERROR_HTML = '<div class="nothing-here-block"><i class="fa fa-warning"></i> Could not load diff</div>'
+ COLLAPSED_HTML = '<div class="nothing-here-block diff-collapsed">This diff is collapsed. Click to expand it.</div>'
+
+ constructor: (@file) ->
+ @content = $('.diff-content', @file)
+ @diffForPath = @content.find('[data-diff-for-path]').data 'diff-for-path'
+ @isOpen = !@diffForPath
+
+ if @diffForPath
+ @collapsedContent = @content
+ @loadingContent = $(WRAPPER).addClass('loading').html(LOADING_HTML).hide()
+ @content = null
+ @collapsedContent.after(@loadingContent)
+ else
+ @collapsedContent = $(WRAPPER).html(COLLAPSED_HTML).hide()
+ @content.after(@collapsedContent)
+
+ @collapsedContent.on 'click', @toggleDiff
+
+ $('.file-title > a', @file).on 'click', @toggleDiff
+
+ toggleDiff: (e) =>
+ @isOpen = !@isOpen
+ if not @isOpen and not @hasError
+ @content.hide()
+ @collapsedContent.show()
+ else if @content
+ @collapsedContent.hide()
+ @content.show()
+ else
+ @getContentHTML()
+
+ getContentHTML: ->
+ @collapsedContent.hide()
+ @loadingContent.show()
+ $.get @diffForPath, (data) =>
+ @loadingContent.hide()
+ if data.html
+ @content = $(data.html)
+ @content.syntaxHighlight()
+ else
+ @hasError = true
+ @content = $(ERROR_HTML)
+ @collapsedContent.after(@content)
+ return
+
+$.fn.singleFileDiff = ->
+ return @each ->
+ if not $.data this, 'singleFileDiff'
+ $.data this, 'singleFileDiff', new SingleFileDiff this
diff --git a/app/assets/javascripts/users/calendar.js.coffee b/app/assets/javascripts/users/calendar.js.coffee
index c081f023b04..c49ba5186f2 100644
--- a/app/assets/javascripts/users/calendar.js.coffee
+++ b/app/assets/javascripts/users/calendar.js.coffee
@@ -87,14 +87,15 @@ class @Calendar
.attr 'width', @daySize
.attr 'height', @daySize
.attr 'title', (stamp) =>
+ date = new Date(stamp.date)
contribText = 'No contributions'
if stamp.count > 0
contribText = "#{stamp.count} contribution#{if stamp.count > 1 then 's' else ''}"
- date = dateFormat(stamp.date, 'mmm d, yyyy')
+ dateText = dateFormat(date, 'mmm d, yyyy')
- "#{contribText}<br />#{date}"
+ "#{contribText}<br />#{gl.utils.getDayName(date)} #{dateText}"
.attr 'class', 'user-contrib-cell js-tooltip'
.attr 'fill', (stamp) =>
if stamp.count isnt 0
diff --git a/app/assets/javascripts/users_select.js.coffee b/app/assets/javascripts/users_select.js.coffee
index 2548efb2186..4e032ab1ff1 100644
--- a/app/assets/javascripts/users_select.js.coffee
+++ b/app/assets/javascripts/users_select.js.coffee
@@ -61,8 +61,8 @@ class @UsersSelect
collapsedAssigneeTemplate = _.template(
'<% if( avatar ) { %>
- <a class="author_link" href="/u/<%= username %>">
- <img width="24" class="avatar avatar-inline s24" alt="" src="<%= avatar %>">
+ <a class="author_link" href="/u/<%- username %>">
+ <img width="24" class="avatar avatar-inline s24" alt="" src="<%- avatar %>">
<span class="author">Toni Boehm</span>
</a>
<% } else { %>
@@ -72,13 +72,13 @@ class @UsersSelect
assigneeTemplate = _.template(
'<% if (username) { %>
- <a class="author_link bold" href="/u/<%= username %>">
+ <a class="author_link bold" href="/u/<%- username %>">
<% if( avatar ) { %>
- <img width="32" class="avatar avatar-inline s32" alt="" src="<%= avatar %>">
+ <img width="32" class="avatar avatar-inline s32" alt="" src="<%- avatar %>">
<% } %>
- <span class="author"><%= name %></span>
+ <span class="author"><%- name %></span>
<span class="username">
- @<%= username %>
+ @<%- username %>
</span>
</a>
<% } else { %>
diff --git a/app/assets/stylesheets/framework/blank.scss b/app/assets/stylesheets/framework/blank.scss
index 40b5171a8c6..d28cda6d62d 100644
--- a/app/assets/stylesheets/framework/blank.scss
+++ b/app/assets/stylesheets/framework/blank.scss
@@ -1,3 +1,12 @@
+.blank-state-welcome {
+ text-align: center;
+ border-bottom: 1px solid $border-color;
+
+ .blank-state-text {
+ margin-bottom: 0;
+ }
+}
+
.blank-state {
padding-top: 20px;
padding-bottom: 20px;
@@ -6,7 +15,15 @@
.blank-state-no-icon {
padding-top: 40px;
- padding-bottom: 40px;
+ padding-bottom: 40px;
+}
+
+.blank-state-icon {
+ padding-bottom: 20px;
+
+ path {
+ fill: $gray-darkest;
+ }
}
.blank-state-title {
@@ -21,3 +38,7 @@
margin-bottom: $gl-padding;
font-size: 15px;
}
+
+.blank-state-welcome-title {
+ font-size: 24px;
+}
diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss
index 41e77a4ac68..24b1ebab4b0 100644
--- a/app/assets/stylesheets/framework/blocks.scss
+++ b/app/assets/stylesheets/framework/blocks.scss
@@ -16,6 +16,9 @@
font-weight: normal;
font-size: 16px;
line-height: 36px;
+ &.diff-collapsed {
+ cursor: pointer;
+ }
}
.row-content-block {
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index 1e3083cce55..590b8f54363 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -281,3 +281,21 @@
color: $gl-icon-color;
}
}
+
+.clone-dropdown-btn a {
+ color: $dropdown-link-color;
+ &:hover {
+ text-decoration: none;
+ }
+}
+
+.btn-static {
+ background-color: $background-color !important;
+ border: 1px solid lightgrey;
+ cursor: default;
+ &:active {
+ -moz-box-shadow: inset 0 0 0 white;
+ -webkit-box-shadow: inset 0 0 0 white;
+ box-shadow: inset 0 0 0 white;
+ }
+}
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 2a90a1fef37..d4e900f80ef 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -23,6 +23,9 @@
.dropdown-menu,
.dropdown-menu-nav {
display: block;
+ @media (max-width: $screen-xs-max) {
+ width: 100%;
+ }
}
.dropdown-menu-toggle {
@@ -65,6 +68,10 @@
color: $dropdown-toggle-hover-icon-color;
}
}
+
+ &.large {
+ width: 200px;
+ }
}
.dropdown-menu,
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index 71a9f79be3e..71e4b50f2af 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -50,7 +50,7 @@
}
a:not(.btn) {
- color: $gl-dark-link-color;
+ color: $gl-text-color;
}
.left-options {
diff --git a/app/assets/stylesheets/framework/flash.scss b/app/assets/stylesheets/framework/flash.scss
index a951a2b97fe..0c21d0240b3 100644
--- a/app/assets/stylesheets/framework/flash.scss
+++ b/app/assets/stylesheets/framework/flash.scss
@@ -1,8 +1,8 @@
.flash-container {
cursor: pointer;
margin: 0;
+ margin-bottom: $gl-padding;
font-size: 14px;
- width: 100%;
z-index: 100;
.flash-notice {
@@ -18,9 +18,27 @@
}
.flash-notice, .flash-alert {
- .container-fluid.flash-text {
+ border-radius: $border-radius-default;
+
+ .container-fluid.container-limited.flash-text {
background: transparent;
}
}
+
+ &.flash-container-page {
+ margin-bottom: 0;
+
+ .flash-notice, .flash-alert {
+ border-radius: 0;
+ }
+ }
+}
+
+@media (max-width: $screen-md-min) {
+ ul.notes {
+ .flash-container.timeline-content {
+ margin-left: 0;
+ }
+ }
}
diff --git a/app/assets/stylesheets/framework/gitlab-theme.scss b/app/assets/stylesheets/framework/gitlab-theme.scss
index 0a8603b6702..d1ff63bd099 100644
--- a/app/assets/stylesheets/framework/gitlab-theme.scss
+++ b/app/assets/stylesheets/framework/gitlab-theme.scss
@@ -20,17 +20,6 @@
.sidebar-wrapper {
background: $color-darker;
-
- .sidebar-user {
- background: $color-darker;
- color: $color-light;
-
- &:hover {
- background-color: $color-dark;
- color: $white-light;
- text-decoration: none;
- }
- }
}
.nav-sidebar li {
diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss
index a12c0bba44a..2c40ec430ca 100644
--- a/app/assets/stylesheets/framework/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -137,6 +137,15 @@ ul.content-list {
padding-top: 1px;
float: right;
+ > .control-text {
+ margin-right: $gl-padding-top;
+ line-height: 40px;
+
+ &:last-child {
+ margin-right: 0;
+ }
+ }
+
> .btn,
> .btn-group {
margin-right: $gl-padding-top;
@@ -166,6 +175,12 @@ ul.content-list {
.panel > .content-list > li {
padding: $gl-padding-top $gl-padding;
+
+ &.commit {
+ @media (min-width: $screen-sm-min) {
+ padding-left: 46px + $gl-padding;
+ }
+ }
}
ul.controls {
diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss
index 6e5f216c894..364952d3b4a 100644
--- a/app/assets/stylesheets/framework/nav.scss
+++ b/app/assets/stylesheets/framework/nav.scss
@@ -77,10 +77,10 @@
&.sub-nav {
text-align: center;
- background-color: $background-color;
+ background-color: $dark-background-color;
.container-fluid {
- background-color: $background-color;
+ background-color: $dark-background-color;
margin-bottom: 0;
}
@@ -134,6 +134,11 @@
margin-bottom: 0;
border-bottom: none;
+ &.wide {
+ width: 100%;
+ display: block;
+ }
+
li a {
padding: 16px 10px 11px;
}
@@ -164,6 +169,7 @@
> .btn {
margin-right: $gl-padding-top;
display: inline-block;
+ vertical-align: top;
&:last-child {
margin-right: 0;
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index e8d6a7f2775..1a2220f3b40 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -3,6 +3,12 @@
padding-bottom: 25px;
transition: padding $sidebar-transition-duration;
+ &.page-sidebar-pinned {
+ .sidebar-wrapper {
+ @include box-shadow(none);
+ }
+ }
+
.sidebar-wrapper {
position: fixed;
top: 0;
@@ -11,6 +17,7 @@
height: 100%;
overflow: hidden;
transition: width $sidebar-transition-duration;
+ @include box-shadow(2px 0 16px 0 #bbb);
}
}
@@ -40,32 +47,16 @@
}
}
-.sidebar-user {
- padding: 15px;
- position: absolute;
- left: 0;
- bottom: 0;
- width: $sidebar_width;
- overflow: hidden;
- font-size: 16px;
- line-height: 36px;
- transition: width $sidebar-transition-duration, padding $sidebar-transition-duration;
-
- @media (min-width: $sidebar-breakpoint) {
- bottom: 50px;
- }
-}
-
.nav-sidebar {
position: absolute;
top: 50px;
- bottom: 65px;
+ bottom: 0;
width: $sidebar_width;
overflow-y: auto;
overflow-x: hidden;
@media (min-width: $sidebar-breakpoint) {
- bottom: 115px;
+ bottom: 50px;
}
&.navbar-collapse {
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 211a9af2348..4337fab5d87 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -12,10 +12,11 @@ $sidebar-breakpoint: 1024px;
/*
* UI elements
*/
-$border-color: #e5e5e5;
-$focus-border-color: #3aabf0;
-$table-border-color: #f0f0f0;
-$background-color: #fafafa;
+$border-color: #e5e5e5;
+$focus-border-color: #3aabf0;
+$table-border-color: #f0f0f0;
+$background-color: #fafafa;
+$dark-background-color: #f7f7f7;
/*
* Text
@@ -153,9 +154,6 @@ $warning-message-bg: #fbf2d9;
$warning-message-color: #9e8e60;
$warning-message-border: #f0e2bb;
-/* header */
-$light-grey-header: #faf9f9;
-
/* tanuki logo colors */
$tanuki-red: #e24329;
$tanuki-orange: #fc6d26;
diff --git a/app/assets/stylesheets/pages/admin.scss b/app/assets/stylesheets/pages/admin.scss
index e05f14e7496..1d34a7f79ae 100644
--- a/app/assets/stylesheets/pages/admin.scss
+++ b/app/assets/stylesheets/pages/admin.scss
@@ -71,3 +71,36 @@
@extend .broadcast-message;
margin-bottom: 20px;
}
+
+
+// Users List
+
+.users-list {
+ .user-row {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ }
+
+ .user-details {
+ flex: 1 1 auto;
+ }
+
+ .user-name {
+ display: inline-block;
+ font-weight: bold;
+ }
+
+ .controls {
+ > .btn, > .dropdown {
+ margin-left: 5px;
+ }
+ }
+
+ .dropdown {
+ .btn-block {
+ margin-bottom: 0;
+ line-height: inherit;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
index 85bbf70e188..0298577c494 100644
--- a/app/assets/stylesheets/pages/commits.scss
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -61,7 +61,7 @@
font-size: 0;
}
- .btn-transparent {
+ .btn-clipboard, .btn-transparent {
padding-left: 0;
padding-right: 0;
}
diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss
index 5286b73cc50..21b1c223c88 100644
--- a/app/assets/stylesheets/pages/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -434,13 +434,3 @@
}
}
}
-
-.discussion {
- .diff-content {
- .diff-line-num {
- &:before {
- content: attr(data-linenumber);
- }
- }
- }
-}
diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss
index 3d79f4400e2..701b9388454 100644
--- a/app/assets/stylesheets/pages/groups.scss
+++ b/app/assets/stylesheets/pages/groups.scss
@@ -38,6 +38,39 @@
margin-right: 15px;
}
}
+
+ &.group-admin {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+
+ .group-avatar, .group-details, .group-controls {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ }
+
+ .group-details {
+ flex: 1 1 auto;
+ flex-direction: column;
+ min-width: 0;
+ }
+
+ .group-controls {
+ align-items: center;
+
+ a {
+ margin-left: 5px;
+ }
+ }
+ }
+
+}
+
+.ldap-group-links {
+ .form-actions {
+ margin-bottom: $gl-padding;
+ }
}
.groups-cover-block {
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index 4e35ca329e4..0e4d8c140aa 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -63,8 +63,8 @@ form.edit-issue {
.merge-request,
.issue {
&.today {
- background: #efe;
- border-color: #cec;
+ background: #f8feef;
+ border-color: #e1e8d5;
}
&.closed {
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 124f4afaa0d..d9756b66af0 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -167,7 +167,8 @@
.commit {
margin: 0;
- padding: 2px 0;
+ padding-top: 2px;
+ padding-bottom: 2px;
list-style: none;
&:hover {
background: none;
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 817c2982923..5be911dc562 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -64,86 +64,49 @@
}
.project-home-panel {
- background: $white-light;
- text-align: left;
- padding: 24px 0;
+ padding-top: 24px;
+ padding-bottom: 24px;
- .container-fluid {
- position: relative;
-
- @media (min-width: $screen-lg-min) {
- .row {
- display: flex;
- -ms-flex-align: center;
- -webkit-align-items: center;
- -webkit-box-align: center;
- }
- }
+ @media (min-width: $screen-sm-min) {
+ border-bottom: 1px solid $border-color;
}
- .cover-controls {
- .project-settings-dropdown {
- margin-left: 10px;
- display: inline-block;
+ .project-avatar {
+ float: none;
+ margin-left: auto;
+ margin-right: auto;
- .dropdown-menu {
- left: auto;
- width: auto;
- right: 0;
- max-width: 240px;
- }
+ &.identicon {
+ border-radius: 50%;
}
}
- .cover-title {
- margin-bottom: 0;
- }
-
- .project-image-container {
- @include make-sm-column(1);
- max-width: 86px;
- min-width: 86px;
- padding-right: 0;
-
- @media (max-width: $screen-md-max) {
- padding-left: 0;
- margin: 0 0 10px;
- max-width: none;
- min-width: none;
+ .project-title {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ font-size: 24px;
+ font-weight: 400;
+ line-height: 1;
- .avatar.s70 {
- margin: auto;
- }
+ .fa {
+ margin-left: 2px;
+ font-size: 12px;
+ vertical-align: middle;
}
}
- .project-info {
- @include make-sm-column(10);
+ .project-home-desc {
+ margin-left: auto;
+ margin-right: auto;
+ margin-bottom: 15px;
+ max-width: 480px;
- h1 {
- font-size: 24px;
- font-weight: normal;
- margin: 0;
+ > p {
+ margin-bottom: 0;
}
-
- .project-home-desc {
- p {
- margin: 0;
- }
- }
- }
-
- .identicon {
- float: left;
- @include border-radius(50%);
- }
-
- .avatar {
- float: none;
}
.notifications-btn {
-
.fa-bell,
.fa-spinner {
margin-right: 6px;
@@ -153,127 +116,106 @@
margin-left: 6px;
}
}
+}
- .project-repo-buttons {
- font-size: 0;
-
- .btn {
- @include btn-gray;
- padding: 3px 10px;
- text-transform: none;
- background-color: $background-color;
+.project-repo-buttons {
+ font-size: 0;
- .fa {
- color: $layout-link-gray;
- }
+ .btn {
+ @include btn-gray;
+ padding: 3px 10px;
- .fa-caret-down {
- margin-left: 3px;
- }
+ .fa {
+ color: $layout-link-gray;
}
- form {
- margin-left: 10px;
+ .fa-caret-down {
+ margin-left: 3px;
}
+ }
- .count-buttons {
- display: inline-block;
- vertical-align: top;
- margin-top: 16px;
- }
+ .project-repo-btn-group,
+ .notification-dropdown {
+ margin-left: 10px;
+ }
- .project-clone-holder {
- display: inline-block;
- margin-top: 16px;
+ .count-buttons {
+ display: inline-block;
+ vertical-align: top;
+ }
- input {
- height: 29px;
- }
+ .project-clone-holder {
+ display: inline-block;
+
+ input {
+ height: 29px;
}
+ }
- .count-with-arrow {
- display: inline-block;
- position: relative;
- margin-left: 4px;
-
- .arrow {
- &:before {
- content: '';
- display: inline-block;
- position: absolute;
- width: 0;
- height: 0;
- border-color: transparent;
- border-style: solid;
- top: 50%;
- left: 0;
- margin-top: -6px;
- border-width: 7px 5px 7px 0;
- border-right-color: #dce0e5;
- }
+ .count-with-arrow {
+ display: inline-block;
+ position: relative;
+ margin-left: 4px;
- &:after {
- content: '';
- position: absolute;
- width: 0;
- height: 0;
- border-color: transparent;
- border-style: solid;
- top: 50%;
- left: 1px;
- margin-top: -9px;
- border-width: 10px 7px 10px 0;
- border-right-color: #fff;
- }
- }
- .count {
- @include btn-gray;
+ .arrow {
+ &:before {
+ content: '';
display: inline-block;
- background: white;
- border-radius: 2px;
- border-width: 1px;
+ position: absolute;
+ width: 0;
+ height: 0;
+ border-color: transparent;
border-style: solid;
- font-size: 13px;
- font-weight: 600;
- line-height: 13px;
- padding: $gl-vert-padding $gl-padding;
- letter-spacing: .4px;
- padding: 7px 14px;
- text-align: center;
- vertical-align: middle;
- touch-action: manipulation;
- cursor: pointer;
- background-image: none;
- white-space: nowrap;
- margin: 0 10px 0 4px;
-
- a {
- color: inherit;
- }
-
- &:hover {
- background: #fff;
- }
+ top: 50%;
+ left: 0;
+ margin-top: -6px;
+ border-width: 7px 5px 7px 0;
+ border-right-color: #dce0e5;
+ pointer-events: none;
}
- }
- }
- .project-right-buttons {
- position: absolute;
- right: 16px;
- bottom: 0;
-
- @media (max-width: $screen-md-max) {
- top: 0;
+ &:after {
+ content: '';
+ position: absolute;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+ top: 50%;
+ left: 1px;
+ margin-top: -9px;
+ border-width: 10px 7px 10px 0;
+ border-right-color: #fff;
+ pointer-events: none;
+ }
}
- }
-
- @media (max-width: $screen-md-max) {
- text-align: center;
+ .count {
+ @include btn-gray;
+ display: inline-block;
+ background: white;
+ border-radius: 2px;
+ border-width: 1px;
+ border-style: solid;
+ font-size: 13px;
+ font-weight: 600;
+ line-height: 13px;
+ padding: $gl-vert-padding $gl-padding;
+ letter-spacing: .4px;
+ padding: 7px 14px;
+ text-align: center;
+ vertical-align: middle;
+ touch-action: manipulation;
+ background-image: none;
+ white-space: nowrap;
+ margin: 0 10px 0 4px;
+
+ a {
+ color: inherit;
+ }
- .project-info,
- .project-image-container {
- width: 100%;
+ &:hover {
+ background: #fff;
+ }
}
}
}
@@ -398,59 +340,72 @@ a.deploy-project-label {
.project-import {
.form-group {
- margin-bottom: 0;
+ margin-bottom: 5px;
}
+
.import-buttons {
padding-left: 0;
display: -webkit-flex;
display: flex;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
+
.btn {
- margin-right: 10px;
- padding: 8px 12px;
+ margin: 0 10px 10px 0;
+ padding: 8px;
}
- &> div {
- margin-bottom: 14px;
+
+ > div {
padding-left: 0;
+
&:last-child {
margin-bottom: 0;
+
+ .btn {
+ margin-right: 0;
+ }
}
}
}
}
.project-stats {
- margin-top: $gl-padding;
- margin-bottom: 0;
- padding: 0;
- background-color: $white-light;
font-size: 0;
+ border-bottom: 1px solid $border-color;
- ul.nav {
- display: inline-block;
+ .nav {
+ padding-top: 12px;
+ padding-bottom: 12px;
}
- .nav li {
+ .nav > li {
display: inline-block;
- margin: 16px 0;
- margin-right: 16px;
+
+ &:not(:last-child) {
+ margin-right: $gl-padding;
+ }
+
+ &.project-repo-buttons-right {
+ margin-top: 10px;
+
+ @media (min-width: $screen-md-min) {
+ float: right;
+ margin-top: 0;
+ }
+ }
}
.nav > li > a {
+ padding: 0;
background-color: transparent;
- padding: 5px 10px;
font-size: 15px;
+ line-height: 29px;
color: $notes-light-color;
- }
-
- li {
- display: inline;
- }
- a {
- float: left;
- font-size: 17px;
+ &:hover,
+ &:focus {
+ color: darken($notes-light-color, 15%);
+ }
}
li.missing {
@@ -458,6 +413,8 @@ a.deploy-project-label {
border-radius: $border-radius-default;
a {
+ padding-left: 10px;
+ padding-right: 10px;
color: $notes-light-color;
display: block;
}
@@ -466,10 +423,6 @@ a.deploy-project-label {
background-color: $gray-normal;
}
}
-
- &.row-content-block.second-block {
- margin-top: 0;
- }
}
pre.light-well {
@@ -529,10 +482,6 @@ pre.light-well {
a:hover {
text-decoration: none;
}
-
- > span {
- margin-left: 10px;
- }
}
}
@@ -557,8 +506,32 @@ pre.light-well {
}
.project-last-commit {
+ @media (min-width: $screen-sm-min) {
+ margin-top: $gl-padding;
+ }
+
+ &.container-fluid {
+ padding-top: 12px;
+ padding-bottom: 12px;
+ background-color: $background-color;
+ border: 1px solid $border-color;
+ border-right-width: 0;
+ border-left-width: 0;
+
+ @media (min-width: $screen-sm-min) {
+ border-right-width: 1px;
+ border-left-width: 1px;
+ }
+ }
+
+ &.container-limited {
+ @media (min-width: 1281px) {
+ border-radius: $border-radius-base;
+ }
+ }
+
.ci-status {
- margin-right: 16px;
+ margin-right: $gl-padding;
}
.commit-row-message {
@@ -566,19 +539,12 @@ pre.light-well {
}
.commit_short_id {
- margin: 0 5px;
+ margin-right: 5px;
color: $gl-link-color;
font-weight: 600;
}
.commit-author-link {
- margin-left: 7px;
- text-decoration: none;
- .avatar {
- float: none;
- margin-right: 4px;
- }
-
.commit-author-name {
font-weight: 600;
}
@@ -601,15 +567,10 @@ pre.light-well {
}
.git-clone-holder {
- width: 498px;
+ width: 380px;
.btn-clipboard {
border: 1px solid $border-color;
- padding: 6px $gl-padding;
- }
-
- .project-home-dropdown + & {
- margin-right: 45px;
}
.clone-options {
diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss
index ae524cd6bae..9e9b18fdbb8 100644
--- a/app/assets/stylesheets/pages/search.scss
+++ b/app/assets/stylesheets/pages/search.scss
@@ -208,7 +208,7 @@
margin-top: 5px;
@media (min-width: $screen-sm-min) {
- width: 160px;
+ width: 180px;
margin-top: 0;
}
}
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 5f65dd3aff0..23ba83aba0e 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -87,6 +87,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:version_check_enabled,
:admin_notification_email,
:user_oauth_applications,
+ :user_default_external,
:shared_runners_enabled,
:shared_runners_text,
:max_artifacts_size,
@@ -110,6 +111,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:send_user_confirmation_email,
:container_registry_token_expire_delay,
:repository_storage,
+ :enabled_git_access_protocol,
restricted_visibility_levels: [],
import_sources: [],
disabled_oauth_sign_in_sources: []
diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb
index 4c9c6362ffc..0d2f4f6eb38 100644
--- a/app/controllers/admin/projects_controller.rb
+++ b/app/controllers/admin/projects_controller.rb
@@ -5,11 +5,12 @@ class Admin::ProjectsController < Admin::ApplicationController
def index
@projects = Project.all
@projects = @projects.in_namespace(params[:namespace_id]) if params[:namespace_id].present?
- @projects = @projects.where("projects.visibility_level IN (?)", params[:visibility_levels]) if params[:visibility_levels].present?
+ @projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present?
@projects = @projects.with_push if params[:with_push].present?
@projects = @projects.abandoned if params[:abandoned].present?
@projects = @projects.where(last_repository_check_failed: true) if params[:last_repository_check_failed].present?
- @projects = @projects.non_archived unless params[:with_archived].present?
+ @projects = @projects.non_archived unless params[:archived].present?
+ @projects = @projects.personal(current_user) if params[:personal].present?
@projects = @projects.search(params[:name]) if params[:name].present?
@projects = @projects.sort(@sort = params[:sort])
@projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page])
diff --git a/app/controllers/concerns/diff_for_path.rb b/app/controllers/concerns/diff_for_path.rb
new file mode 100644
index 00000000000..e09b8789eb2
--- /dev/null
+++ b/app/controllers/concerns/diff_for_path.rb
@@ -0,0 +1,25 @@
+module DiffForPath
+ extend ActiveSupport::Concern
+
+ def render_diff_for_path(diffs, diff_refs, project)
+ diff_file = safe_diff_files(diffs, diff_refs: diff_refs, repository: project.repository).find do |diff|
+ diff.old_path == params[:old_path] && diff.new_path == params[:new_path]
+ end
+
+ return render_404 unless diff_file
+
+ diff_commit = commit_for_diff(diff_file)
+ blob = diff_file.blob(diff_commit)
+ @expand_all_diffs = true
+
+ locals = {
+ diff_file: diff_file,
+ diff_commit: diff_commit,
+ diff_refs: diff_refs,
+ blob: blob,
+ project: project
+ }
+
+ render json: { html: view_to_html_string('projects/diffs/_content', locals) }
+ end
+end
diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb
index 9b5c43b17e2..d3dd98c8a4e 100644
--- a/app/controllers/help_controller.rb
+++ b/app/controllers/help_controller.rb
@@ -12,13 +12,12 @@ class HelpController < ApplicationController
end
def show
- @category = clean_path_info(path_params[:category])
- @file = path_params[:file]
+ @path = clean_path_info(path_params[:path])
respond_to do |format|
format.any(:markdown, :md, :html) do
# Note: We are purposefully NOT using `Rails.root.join`
- path = File.join(Rails.root, 'doc', @category, "#{@file}.md")
+ path = File.join(Rails.root, 'doc', "#{@path}.md")
if File.exist?(path)
@markdown = File.read(path)
@@ -33,7 +32,7 @@ class HelpController < ApplicationController
# Allow access to images in the doc folder
format.any(:png, :gif, :jpeg) do
# Note: We are purposefully NOT using `Rails.root.join`
- path = File.join(Rails.root, 'doc', @category, "#{@file}.#{params[:format]}")
+ path = File.join(Rails.root, 'doc', "#{@path}.#{params[:format]}")
if File.exist?(path)
send_file(path, disposition: 'inline')
@@ -57,8 +56,7 @@ class HelpController < ApplicationController
private
def path_params
- params.require(:category)
- params.require(:file)
+ params.require(:path)
params
end
diff --git a/app/controllers/import/gitlab_projects_controller.rb b/app/controllers/import/gitlab_projects_controller.rb
index 513348c39af..30df1fb2fec 100644
--- a/app/controllers/import/gitlab_projects_controller.rb
+++ b/app/controllers/import/gitlab_projects_controller.rb
@@ -27,10 +27,7 @@ class Import::GitlabProjectsController < Import::BaseController
notice: "Project '#{@project.name}' is being imported."
)
else
- redirect_to(
- new_import_gitlab_project_path,
- alert: "Project could not be imported: #{@project.errors.full_messages.join(', ')}"
- )
+ redirect_back_or_default(options: { alert: "Project could not be imported: #{@project.errors.full_messages.join(', ')}" })
end
end
diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb
index f11c8321464..7241949393b 100644
--- a/app/controllers/projects/artifacts_controller.rb
+++ b/app/controllers/projects/artifacts_controller.rb
@@ -23,10 +23,9 @@ class Projects::ArtifactsController < Projects::ApplicationController
entry = build.artifacts_metadata_entry(params[:path])
if entry.exists?
- render json: { archive: build.artifacts_file.path,
- entry: Base64.encode64(entry.path) }
+ send_artifacts_entry(build, entry)
else
- render json: {}, status: 404
+ render_404
end
end
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 7599fec3cdf..5356fdf010d 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -57,7 +57,7 @@ class Projects::BlobController < Projects::ApplicationController
diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true)
diff_lines = diffy.diff.scan(/.*\n/)[2..-1]
diff_lines = Gitlab::Diff::Parser.new.parse(diff_lines)
- @diff_lines = Gitlab::Diff::Highlight.new(diff_lines).highlight
+ @diff_lines = Gitlab::Diff::Highlight.new(diff_lines, repository: @repository).highlight
render layout: false
end
diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb
index d162a5a3165..727e84b40a1 100644
--- a/app/controllers/projects/commit_controller.rb
+++ b/app/controllers/projects/commit_controller.rb
@@ -3,6 +3,7 @@
# Not to be confused with CommitsController, plural.
class Projects::CommitController < Projects::ApplicationController
include CreatesCommit
+ include DiffForPath
include DiffHelper
# Authorize
@@ -11,29 +12,14 @@ class Projects::CommitController < Projects::ApplicationController
before_action :authorize_update_build!, only: [:cancel_builds, :retry_builds]
before_action :authorize_read_commit_status!, only: [:builds]
before_action :commit
- before_action :define_show_vars, only: [:show, :builds]
+ before_action :define_commit_vars, only: [:show, :diff_for_path, :builds]
+ before_action :define_status_vars, only: [:show, :builds]
+ before_action :define_note_vars, only: [:show, :diff_for_path]
before_action :authorize_edit_tree!, only: [:revert, :cherry_pick]
def show
apply_diff_view_cookie!
- @grouped_diff_notes = commit.notes.grouped_diff_notes
- @notes = commit.notes.non_diff_notes.fresh
-
- Banzai::NoteRenderer.render(
- @grouped_diff_notes.values.flatten + @notes,
- @project,
- current_user,
- )
-
- @note = @project.build_commit_note(commit)
-
- @noteable = @commit
- @comments_target = {
- noteable_type: 'Commit',
- commit_id: @commit.id
- }
-
respond_to do |format|
format.html
format.diff { render text: @commit.to_diff }
@@ -41,6 +27,10 @@ class Projects::CommitController < Projects::ApplicationController
end
end
+ def diff_for_path
+ render_diff_for_path(@diffs, @commit.diff_refs, @project)
+ end
+
def builds
end
@@ -114,16 +104,36 @@ class Projects::CommitController < Projects::ApplicationController
@ci_builds ||= Ci::Build.where(pipeline: pipelines)
end
- def define_show_vars
+ def define_commit_vars
return git_not_found! unless commit
opts = diff_options
opts[:ignore_whitespace_change] = true if params[:format] == 'diff'
@diffs = commit.diffs(opts)
- @diff_refs = [commit.parent || commit, commit]
@notes_count = commit.notes.count
+ end
+
+ def define_note_vars
+ @grouped_diff_notes = commit.notes.grouped_diff_notes
+ @notes = commit.notes.non_diff_notes.fresh
+
+ Banzai::NoteRenderer.render(
+ @grouped_diff_notes.values.flatten + @notes,
+ @project,
+ current_user,
+ )
+
+ @note = @project.build_commit_note(commit)
+
+ @noteable = @commit
+ @comments_target = {
+ noteable_type: 'Commit',
+ commit_id: @commit.id
+ }
+ end
+ def define_status_vars
@statuses = CommitStatus.where(pipeline: pipelines)
@builds = Ci::Build.where(pipeline: pipelines)
end
diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb
index af0b69a2442..5f3ee71444d 100644
--- a/app/controllers/projects/compare_controller.rb
+++ b/app/controllers/projects/compare_controller.rb
@@ -1,30 +1,26 @@
require 'addressable/uri'
class Projects::CompareController < Projects::ApplicationController
+ include DiffForPath
include DiffHelper
# Authorize
before_action :require_non_empty_project
before_action :authorize_download_code!
- before_action :assign_ref_vars, only: [:index, :show]
+ before_action :define_ref_vars, only: [:index, :show, :diff_for_path]
+ before_action :define_diff_vars, only: [:show, :diff_for_path]
before_action :merge_request, only: [:index, :show]
def index
end
def show
- compare = CompareService.new.
- execute(@project, @head_ref, @project, @base_ref, diff_options)
+ end
- if compare
- @commits = Commit.decorate(compare.commits, @project)
- @commit = @project.commit(@head_ref)
- @base_commit = @project.merge_base_commit(@base_ref, @head_ref)
- @diffs = compare.diffs(diff_options)
- @diff_refs = [@base_commit, @commit]
- @diff_notes_disabled = true
- @grouped_diff_notes = {}
- end
+ def diff_for_path
+ return render_404 unless @compare
+
+ render_diff_for_path(@diffs, @diff_refs, @project)
end
def create
@@ -34,13 +30,35 @@ class Projects::CompareController < Projects::ApplicationController
private
- def assign_ref_vars
- @base_ref = Addressable::URI.unescape(params[:from])
+ def define_ref_vars
+ @start_ref = Addressable::URI.unescape(params[:from])
@ref = @head_ref = Addressable::URI.unescape(params[:to])
end
+ def define_diff_vars
+ @compare = CompareService.new.execute(@project, @head_ref, @project, @start_ref)
+
+ if @compare
+ @commits = Commit.decorate(@compare.commits, @project)
+
+ @start_commit = @project.commit(@start_ref)
+ @commit = @project.commit(@head_ref)
+ @base_commit = @project.merge_base_commit(@start_ref, @head_ref)
+
+ @diffs = @compare.diffs(diff_options)
+ @diff_refs = Gitlab::Diff::DiffRefs.new(
+ base_sha: @base_commit.try(:sha),
+ start_sha: @start_commit.try(:sha),
+ head_sha: @commit.try(:sha)
+ )
+
+ @diff_notes_disabled = true
+ @grouped_diff_notes = {}
+ end
+ end
+
def merge_request
@merge_request ||= @project.merge_requests.opened.
- find_by(source_project: @project, source_branch: @head_ref, target_branch: @base_ref)
+ find_by(source_project: @project, source_branch: @head_ref, target_branch: @start_ref)
end
end
diff --git a/app/controllers/projects/git_http_controller.rb b/app/controllers/projects/git_http_controller.rb
index 62c3fa8de53..40a8b7940d9 100644
--- a/app/controllers/projects/git_http_controller.rb
+++ b/app/controllers/projects/git_http_controller.rb
@@ -19,6 +19,8 @@ class Projects::GitHttpController < Projects::ApplicationController
render_ok
elsif receive_pack? && receive_pack_allowed?
render_ok
+ elsif http_blocked?
+ render_not_allowed
else
render_not_found
end
@@ -154,6 +156,10 @@ class Projects::GitHttpController < Projects::ApplicationController
render plain: 'Not Found', status: :not_found
end
+ def render_not_allowed
+ render plain: download_access.message, status: :forbidden
+ end
+
def ci?
@ci.present?
end
@@ -162,12 +168,28 @@ class Projects::GitHttpController < Projects::ApplicationController
return false unless Gitlab.config.gitlab_shell.upload_pack
if user
- Gitlab::GitAccess.new(user, project).download_access_check.allowed?
+ download_access.allowed?
else
ci? || project.public?
end
end
+ def access
+ return @access if defined?(@access)
+
+ @access = Gitlab::GitAccess.new(user, project, 'http')
+ end
+
+ def download_access
+ return @download_access if defined?(@download_access)
+
+ @download_access = access.check('git-upload-pack')
+ end
+
+ def http_blocked?
+ !access.protocol_allowed?
+ end
+
def receive_pack_allowed?
return false unless Gitlab.config.gitlab_shell.receive_pack
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index dd86b940a08..df659bb8c3b 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -1,5 +1,6 @@
class Projects::MergeRequestsController < Projects::ApplicationController
include ToggleSubscriptionAction
+ include DiffForPath
include DiffHelper
include IssuableActions
include ToggleAwardEmoji
@@ -9,10 +10,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController
:edit, :update, :show, :diffs, :commits, :builds, :merge, :merge_check,
:ci_status, :toggle_subscription, :cancel_merge_when_build_succeeds, :remove_wip
]
- before_action :closes_issues, only: [:edit, :update, :show, :diffs, :commits, :builds]
before_action :validates_merge_request, only: [:show, :diffs, :commits, :builds]
before_action :define_show_vars, only: [:show, :diffs, :commits, :builds]
before_action :define_widget_vars, only: [:merge, :cancel_merge_when_build_succeeds, :merge_check]
+ before_action :define_commit_vars, only: [:diffs]
+ before_action :define_diff_comment_vars, only: [:diffs]
before_action :ensure_ref_fetched, only: [:show, :diffs, :commits, :builds]
# Allow read any merge_request
@@ -53,19 +55,19 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
def show
- @note_counts = Note.where(commit_id: @merge_request.commits.map(&:id)).
- group(:commit_id).count
-
respond_to do |format|
- format.html
- format.json { render json: @merge_request }
+ format.html { define_discussion_vars }
+
+ format.json do
+ render json: @merge_request
+ end
+
format.patch do
- headers.store(*Gitlab::Workhorse.send_git_patch(@project.repository,
- @merge_request.diff_base_commit.id,
- @merge_request.last_commit.id))
- headers['Content-Disposition'] = 'inline'
- head :ok
+ return render_404 unless @merge_request.diff_refs
+
+ send_git_patch @project.repository, @merge_request.diff_refs
end
+
format.diff do
return render_404 unless @merge_request.diff_refs
@@ -77,52 +79,65 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def diffs
apply_diff_view_cookie!
- @commit = @merge_request.last_commit
- @base_commit = @merge_request.diff_base_commit
-
- # MRs created before 8.4 don't have a diff_base_commit,
- # but we need it for the "View file @ ..." link by deleted files
- @base_commit ||= @merge_request.first_commit.parent || @merge_request.first_commit
-
- @comments_target = {
- noteable_type: 'MergeRequest',
- noteable_id: @merge_request.id
- }
-
- @grouped_diff_notes = @merge_request.notes.grouped_diff_notes
-
- Banzai::NoteRenderer.render(
- @grouped_diff_notes.values.flatten,
- @project,
- current_user,
- @path,
- @project_wiki,
- @ref
- )
+ @merge_request_diff = @merge_request.merge_request_diff
respond_to do |format|
- format.html
+ format.html { define_discussion_vars }
format.json { render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") } }
end
end
+ # With an ID param, loads the MR at that ID. Otherwise, accepts the same params as #new
+ # and uses that (unsaved) MR.
+ #
+ def diff_for_path
+ if params[:id]
+ merge_request
+ define_diff_comment_vars
+ else
+ build_merge_request
+ @diff_notes_disabled = true
+ @grouped_diff_notes = {}
+ end
+
+ define_commit_vars
+ diffs = @merge_request.diffs(diff_options)
+
+ render_diff_for_path(diffs, @merge_request.diff_refs, @merge_request.project)
+ end
+
def commits
respond_to do |format|
- format.html { render 'show' }
- format.json { render json: { html: view_to_html_string('projects/merge_requests/show/_commits') } }
+ format.html do
+ define_discussion_vars
+
+ render 'show'
+ end
+ format.json do
+ # Get commits from repository
+ # or from cache if already merged
+ @commits = @merge_request.commits
+ @note_counts = Note.where(commit_id: @commits.map(&:id)).
+ group(:commit_id).count
+
+ render json: { html: view_to_html_string('projects/merge_requests/show/_commits') }
+ end
end
end
def builds
respond_to do |format|
- format.html { render 'show' }
+ format.html do
+ define_discussion_vars
+
+ render 'show'
+ end
format.json { render json: { html: view_to_html_string('projects/merge_requests/show/_builds') } }
end
end
def new
- params[:merge_request] ||= ActionController::Parameters.new(source_project: @project)
- @merge_request = MergeRequests::BuildService.new(project, current_user, merge_request_params).execute
+ build_merge_request
@noteable = @merge_request
@target_branches = if @merge_request.target_project
@@ -134,7 +149,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@target_project = merge_request.target_project
@source_project = merge_request.source_project
@commits = @merge_request.compare_commits.reverse
- @commit = @merge_request.last_commit
+ @commit = @merge_request.diff_head_commit
@base_commit = @merge_request.diff_base_commit
@diffs = @merge_request.compare.diffs(diff_options) if @merge_request.compare
@diff_notes_disabled = true
@@ -212,7 +227,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
return
end
- if params[:sha] != @merge_request.source_sha
+ if params[:sha] != @merge_request.diff_head_sha
@status = :sha_mismatch
return
end
@@ -274,16 +289,16 @@ class Projects::MergeRequestsController < Projects::ApplicationController
status ||= "preparing"
else
ci_service = @merge_request.source_project.ci_service
- status = ci_service.commit_status(merge_request.last_commit.sha, merge_request.source_branch) if ci_service
+ status = ci_service.commit_status(merge_request.diff_head_sha, merge_request.source_branch) if ci_service
if ci_service.respond_to?(:commit_coverage)
- coverage = ci_service.commit_coverage(merge_request.last_commit.sha, merge_request.source_branch)
+ coverage = ci_service.commit_coverage(merge_request.diff_head_sha, merge_request.source_branch)
end
end
response = {
title: merge_request.title,
- sha: merge_request.last_commit_short_sha,
+ sha: merge_request.diff_head_commit.short_id,
status: status,
coverage: coverage
}
@@ -308,10 +323,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
alias_method :issuable, :merge_request
alias_method :awardable, :merge_request
- def closes_issues
- @closes_issues ||= @merge_request.closes_issues
- end
-
def authorize_update_merge_request!
return render_404 unless can?(current_user, :update_merge_request, @merge_request)
end
@@ -340,14 +351,30 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
def define_show_vars
+ @noteable = @merge_request
+ @commits_count = @merge_request.commits.count
+
+ @pipeline = @merge_request.pipeline
+ @statuses = @pipeline.statuses if @pipeline
+
+ if @merge_request.locked_long_ago?
+ @merge_request.unlock_mr
+ @merge_request.close
+ end
+ end
+
+ # Discussion tab data is rendered on html responses of actions
+ # :show, :diff, :commits, :builds. but not when request the data through AJAX
+ def define_discussion_vars
# Build a note object for comment form
- @note = @project.notes.new(noteable: @merge_request)
+ @note = @project.notes.new(noteable: @noteable)
- @discussions = @merge_request.mr_and_commit_notes.
+ @discussions = @noteable.mr_and_commit_notes.
inc_author_project_award_emoji.
fresh.
discussions
+ # This is not executed lazily
@notes = Banzai::NoteRenderer.render(
@discussions.flatten,
@project,
@@ -356,28 +383,35 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@project_wiki,
@ref
)
-
- @noteable = @merge_request
-
- # Get commits from repository
- # or from cache if already merged
- @commits = @merge_request.commits
-
- @merge_request_diff = @merge_request.merge_request_diff
-
- @pipeline = @merge_request.pipeline
- @statuses = @pipeline.statuses if @pipeline
-
- if @merge_request.locked_long_ago?
- @merge_request.unlock_mr
- @merge_request.close
- end
end
def define_widget_vars
@pipeline = @merge_request.pipeline
@pipelines = [@pipeline].compact
- closes_issues
+ end
+
+ def define_commit_vars
+ @commit = @merge_request.diff_head_commit
+ @base_commit = @merge_request.diff_base_commit || @merge_request.likely_diff_base_commit
+ end
+
+ def define_diff_comment_vars
+ @comments_target = {
+ noteable_type: 'MergeRequest',
+ noteable_id: @merge_request.id
+ }
+
+ @use_legacy_diff_notes = !@merge_request.support_new_diff_notes?
+ @grouped_diff_notes = @merge_request.notes.grouped_diff_notes
+
+ Banzai::NoteRenderer.render(
+ @grouped_diff_notes.values.flatten,
+ @project,
+ current_user,
+ @path,
+ @project_wiki,
+ @ref
+ )
end
def invalid_mr
@@ -408,4 +442,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController
params[:merge_when_build_succeeds].present? &&
@merge_request.pipeline && @merge_request.pipeline.active?
end
+
+ def build_merge_request
+ params[:merge_request] ||= ActionController::Parameters.new(source_project: @project)
+ @merge_request = MergeRequests::BuildService.new(project, current_user, merge_request_params).execute
+ end
end
diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb
index e14fe26dde7..3eacdbbd067 100644
--- a/app/controllers/projects/notes_controller.rb
+++ b/app/controllers/projects/notes_controller.rb
@@ -128,7 +128,7 @@ class Projects::NotesController < Projects::ApplicationController
elsif note.valid?
Banzai::NoteRenderer.render([note], @project, current_user)
- {
+ attrs = {
valid: true,
id: note.id,
discussion_id: note.discussion_id,
@@ -138,6 +138,23 @@ class Projects::NotesController < Projects::ApplicationController
discussion_html: note_to_discussion_html(note),
discussion_with_diff_html: note_to_discussion_with_diff_html(note)
}
+
+ # The discussion_id is used to add the comment to the correct discussion
+ # element on the merge request page. Among other things, the discussion_id
+ # contains the sha of head commit of the merge request.
+ # When new commits are pushed into the merge request after the initial
+ # load of the merge request page, the discussion elements will still have
+ # the old discussion_ids, with the old head commit sha. The new comment,
+ # however, will have the new discussion_id with the new commit sha.
+ # To ensure that these new comments will still end up in the correct
+ # discussion element, we also send the original discussion_id, with the
+ # old commit sha, along, and fall back on this value when no discussion
+ # element with the new discussion_id could be found.
+ if note.new_diff_note? && note.position != note.original_position
+ attrs[:original_discussion_id] = note.original_discussion_id
+ end
+
+ attrs
else
{
valid: false,
@@ -154,7 +171,7 @@ class Projects::NotesController < Projects::ApplicationController
def note_params
params.require(:note).permit(
:note, :noteable, :noteable_id, :noteable_type, :project_id,
- :attachment, :line_code, :commit_id, :type
+ :attachment, :line_code, :commit_id, :type, :position
)
end
diff --git a/app/controllers/projects/protected_branches_controller.rb b/app/controllers/projects/protected_branches_controller.rb
index efa7bf14d0f..80dad758afa 100644
--- a/app/controllers/projects/protected_branches_controller.rb
+++ b/app/controllers/projects/protected_branches_controller.rb
@@ -2,12 +2,14 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
# Authorize
before_action :require_non_empty_project
before_action :authorize_admin_project!
+ before_action :load_protected_branch, only: [:show, :update, :destroy]
layout "project_settings"
def index
- @branches = @project.protected_branches.to_a
+ @protected_branches = @project.protected_branches.order(:name).page(params[:page])
@protected_branch = @project.protected_branches.new
+ gon.push({ open_branches: @project.open_branches.map { |br| { text: br.name, id: br.name, title: br.name } } })
end
def create
@@ -16,26 +18,24 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
@project)
end
- def update
- protected_branch = @project.protected_branches.find(params[:id])
-
- if protected_branch &&
- protected_branch.update_attributes(
- developers_can_push: params[:developers_can_push]
- )
+ def show
+ @matching_branches = @protected_branch.matching(@project.repository.branches)
+ end
+ def update
+ if @protected_branch && @protected_branch.update_attributes(protected_branch_params)
respond_to do |format|
- format.json { render json: protected_branch, status: :ok }
+ format.json { render json: @protected_branch, status: :ok }
end
else
respond_to do |format|
- format.json { render json: protected_branch.errors, status: :unprocessable_entity }
+ format.json { render json: @protected_branch.errors, status: :unprocessable_entity }
end
end
end
def destroy
- @project.protected_branches.find(params[:id]).destroy
+ @protected_branch.destroy
respond_to do |format|
format.html { redirect_to namespace_project_protected_branches_path }
@@ -45,6 +45,10 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
private
+ def load_protected_branch
+ @protected_branch = @project.protected_branches.find(params[:id])
+ end
+
def protected_branch_params
params.require(:protected_branch).permit(:name, :developers_can_push)
end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 12e0d5a8413..1803aa8eab4 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -53,11 +53,11 @@ class ProjectsController < Projects::ApplicationController
notice: "Project '#{@project.name}' was successfully updated."
)
end
- format.js
else
format.html { render 'edit' }
- format.js
end
+
+ format.js
end
end
diff --git a/app/helpers/appearances_helper.rb b/app/helpers/appearances_helper.rb
index f240584ccbf..950f323e383 100644
--- a/app/helpers/appearances_helper.rb
+++ b/app/helpers/appearances_helper.rb
@@ -31,7 +31,7 @@ module AppearancesHelper
end
end
- def navbar_icon(icon_name)
- render "shared/icons/#{icon_name}.svg"
+ def navbar_icon(icon_name, size: 16)
+ render "shared/icons/#{icon_name}.svg", size: size
end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 62d13a4b4f3..03495cf5ec4 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -306,4 +306,15 @@ module ApplicationHelper
def truncate_first_line(message, length = 50)
truncate(message.each_line.first.chomp, length: length) if message
end
+
+ # While similarly named to Rails's `link_to_if`, this method behaves quite differently.
+ # If `condition` is truthy, a link will be returned with the result of the block
+ # as its body. If `condition` is falsy, only the result of the block will be returned.
+ def conditional_link_to(condition, options, html_options = {}, &block)
+ if condition
+ link_to options, html_options, &block
+ else
+ capture(&block)
+ end
+ end
end
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 6e580c62ccd..78c0b79d2bd 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -31,6 +31,28 @@ module ApplicationSettingsHelper
current_application_settings.akismet_enabled?
end
+ def allowed_protocols_present?
+ current_application_settings.enabled_git_access_protocol.present?
+ end
+
+ def enabled_protocol
+ case current_application_settings.enabled_git_access_protocol
+ when 'http'
+ gitlab_config.protocol
+ when 'ssh'
+ 'ssh'
+ end
+ end
+
+ def enabled_project_button(project, protocol)
+ case protocol
+ when 'ssh'
+ ssh_clone_button(project, 'bottom', append_link: false)
+ else
+ http_clone_button(project, 'bottom', append_link: false)
+ end
+ end
+
# Return a group of checkboxes that use Bootstrap's button plugin for a
# toggle button effect.
def restricted_level_checkboxes(help_block_id)
diff --git a/app/helpers/branches_helper.rb b/app/helpers/branches_helper.rb
index c533659b600..601df5c18df 100644
--- a/app/helpers/branches_helper.rb
+++ b/app/helpers/branches_helper.rb
@@ -12,7 +12,7 @@ module BranchesHelper
def can_push_branch?(project, branch_name)
return false unless project.repository.branch_exists?(branch_name)
- ::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(branch_name)
+ ::Gitlab::GitAccess.new(current_user, project, 'web').can_push_to_branch?(branch_name)
end
def project_branches
diff --git a/app/helpers/button_helper.rb b/app/helpers/button_helper.rb
index 9051a493b9b..b478580978b 100644
--- a/app/helpers/button_helper.rb
+++ b/app/helpers/button_helper.rb
@@ -15,58 +15,42 @@ module ButtonHelper
#
# See http://clipboardjs.com/#usage
def clipboard_button(data = {})
+ data = { toggle: 'tooltip', placement: 'bottom', container: 'body' }.merge(data)
content_tag :button,
icon('clipboard'),
class: "btn btn-clipboard",
data: data,
- type: :button
+ type: :button,
+ title: "Copy to Clipboard"
end
- # Output a "Copy to Clipboard" button with a custom CSS class
- #
- # data - Data attributes passed to `content_tag`
- # css_class - Class passed to the `content_tag`
- #
- # Examples:
- #
- # # Define the target element
- # clipboard_button_with_class({clipboard_target: "div#foo"}, css_class: "btn-clipboard")
- # # => "<button class='btn btn-clipboard' data-clipboard-target='div#foo'>...</button>"
- def clipboard_button_with_class(data = {}, css_class: 'btn-clipboard')
- content_tag :button,
- icon('clipboard'),
- class: "btn #{css_class}",
- data: data,
- type: :button
- end
-
- def http_clone_button(project)
+ def http_clone_button(project, placement = 'right', append_link: true)
klass = 'http-selector'
klass << ' has-tooltip' if current_user.try(:require_password?)
protocol = gitlab_config.protocol.upcase
- content_tag :a, protocol,
+ content_tag (append_link ? :a : :span), protocol,
class: klass,
- href: project.http_url_to_repo,
+ href: (project.http_url_to_repo if append_link),
data: {
html: true,
- placement: 'right',
+ placement: placement,
container: 'body',
title: "Set a password on your account<br>to pull or push via #{protocol}"
}
end
- def ssh_clone_button(project)
+ def ssh_clone_button(project, placement = 'right', append_link: true)
klass = 'ssh-selector'
klass << ' has-tooltip' if current_user.try(:require_ssh_key?)
- content_tag :a, 'SSH',
+ content_tag (append_link ? :a : :span), 'SSH',
class: klass,
- href: project.ssh_url_to_repo,
+ href: (project.ssh_url_to_repo if append_link),
data: {
html: true,
- placement: 'right',
+ placement: placement,
container: 'body',
title: 'Add an SSH key to your profile<br>to pull or push via SSH.'
}
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index e22dce59d0f..adab901700c 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -8,6 +8,10 @@ module DiffHelper
[marked_old_line, marked_new_line]
end
+ def expand_all_diffs?
+ @expand_all_diffs || params[:expand_all_diffs].present?
+ end
+
def diff_view
diff_views = %w(inline parallel)
@@ -18,28 +22,22 @@ module DiffHelper
end
end
- def diff_hard_limit_enabled?
- params[:force_show_diff].present?
- end
-
def diff_options
- options = { ignore_whitespace_change: hide_whitespace? }
- if diff_hard_limit_enabled?
- options.merge!(Commit.max_diff_options)
+ default_options = Commit.max_diff_options
+
+ if action_name == 'diff_for_path'
+ default_options[:paths] = params.values_at(:old_path, :new_path)
end
- options
- end
- def safe_diff_files(diffs, diff_refs)
- diffs.decorate! { |diff| Gitlab::Diff::File.new(diff, diff_refs) }
+ default_options.merge(ignore_whitespace_change: hide_whitespace?)
end
- def generate_line_code(file_path, line)
- Gitlab::Diff::LineCode.generate(file_path, line.new_pos, line.old_pos)
+ def safe_diff_files(diffs, diff_refs: nil, repository: nil)
+ diffs.decorate! { |diff| Gitlab::Diff::File.new(diff, diff_refs: diff_refs, repository: repository) }
end
def unfold_bottom_class(bottom)
- bottom ? 'js-unfold-bottom' : ''
+ bottom ? 'js-unfold js-unfold-bottom' : ''
end
def unfold_class(unfold)
@@ -93,6 +91,8 @@ module DiffHelper
end
def commit_for_diff(diff_file)
+ return diff_file.content_commit if diff_file.content_commit
+
if diff_file.deleted_file
@base_commit || @commit.parent || @commit
else
@@ -100,10 +100,11 @@ module DiffHelper
end
end
- def diff_file_html_data(project, diff_commit, diff_file)
+ def diff_file_html_data(project, diff_file)
+ commit = commit_for_diff(diff_file)
{
blob_diff_path: namespace_project_blob_diff_path(project.namespace, project,
- tree_join(diff_commit.id, diff_file.file_path))
+ tree_join(commit.id, diff_file.file_path))
}
end
diff --git a/app/helpers/dropdowns_helper.rb b/app/helpers/dropdowns_helper.rb
index 7c140538012..4566f3782cc 100644
--- a/app/helpers/dropdowns_helper.rb
+++ b/app/helpers/dropdowns_helper.rb
@@ -39,7 +39,7 @@ module DropdownsHelper
end
end
- def dropdown_toggle(toggle_text, data_attr, options)
+ def dropdown_toggle(toggle_text, data_attr, options = {})
content_tag(:button, class: "dropdown-menu-toggle #{options[:toggle_class] if options.has_key?(:toggle_class)}", id: (options[:id] if options.has_key?(:id)), type: "button", data: data_attr) do
output = content_tag(:span, toggle_text, class: "dropdown-toggle-text")
output << icon('chevron-down')
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index 72bd1fbbd81..2b0defd1dda 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -118,7 +118,7 @@ module IssuesHelper
end
def emoji_icon(name, unicode = nil, aliases = [], sprite: true)
- unicode ||= Emoji.emoji_filename(name) rescue ""
+ unicode ||= Gitlab::Emoji.emoji_filename(name) rescue ""
data = {
aliases: aliases.join(" "),
diff --git a/app/helpers/members_helper.rb b/app/helpers/members_helper.rb
index c70cd19b587..ec106418f2d 100644
--- a/app/helpers/members_helper.rb
+++ b/app/helpers/members_helper.rb
@@ -12,17 +12,6 @@ module MembersHelper
can?(current_user, action_member_permission(:admin, member), member.source)
end
- def can_see_request_access_button?(source)
- source_parent = source.respond_to?(:group) && source.group
-
- return false if source_parent && source.group.members.exists?(user_id: current_user.id)
- return false if source_parent && source.group.requesters.exists?(user_id: current_user.id)
- return false if source.members.exists?(user_id: current_user.id)
- return true if source.requesters.exists?(user_id: current_user.id)
-
- true
- end
-
def remove_member_message(member, user: nil)
user = current_user if defined?(current_user)
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index 1dd07a2a220..db6e731c744 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -27,7 +27,7 @@ module MergeRequestsHelper
end
def ci_build_details_path(merge_request)
- build_url = merge_request.source_project.ci_service.build_page(merge_request.last_commit.sha, merge_request.source_branch)
+ build_url = merge_request.source_project.ci_service.build_page(merge_request.diff_head_sha, merge_request.source_branch)
return nil unless build_url
parsed_url = URI.parse(build_url)
@@ -55,6 +55,10 @@ module MergeRequestsHelper
end.sort.to_sentence
end
+ def mr_closes_issues
+ @mr_closes_issues ||= @merge_request.closes_issues
+ end
+
def mr_change_branches_path(merge_request)
new_namespace_project_merge_request_path(
@project.namespace, @project,
@@ -92,4 +96,8 @@ module MergeRequestsHelper
["#{source_path}:#{source_branch}", "#{target_path}:#{target_branch}"]
end
end
+
+ def merge_request_button_visibility(merge_request, closed)
+ return 'hidden' if merge_request.closed? == closed || (merge_request.merged? == closed && !merge_request.closed?)
+ end
end
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
index e85ba76887d..98143dcee9b 100644
--- a/app/helpers/notes_helper.rb
+++ b/app/helpers/notes_helper.rb
@@ -24,28 +24,61 @@ module NotesHelper
}.to_json
end
- def link_to_new_diff_note(line_code, line_type = nil)
- discussion_id = LegacyDiffNote.build_discussion_id(
- @comments_target[:noteable_type],
- @comments_target[:noteable_id] || @comments_target[:commit_id],
- line_code
- )
+ def diff_view_data
+ return {} unless @comments_target
+
+ @comments_target.slice(:noteable_id, :noteable_type, :commit_id)
+ end
+
+ def diff_view_line_data(line_code, position, line_type)
+ return if @diff_notes_disabled
+
+ use_legacy_diff_note = @use_legacy_diff_notes
+ # If the controller doesn't force the use of legacy diff notes, we
+ # determine this on a line-by-line basis by seeing if there already exist
+ # active legacy diff notes at this line, in which case newly created notes
+ # will use the legacy technology as well.
+ # We do this because the discussion_id values of legacy and "new" diff
+ # notes, which are used to group notes on the merge request discussion tab,
+ # are incompatible.
+ # If we didn't, diff notes that would show for the same line on the changes
+ # tab, would show in different discussions on the discussion tab.
+ use_legacy_diff_note ||= begin
+ line_diff_notes = @grouped_diff_notes[line_code]
+ line_diff_notes && line_diff_notes.any?(&:legacy_diff_note?)
+ end
data = {
- noteable_type: @comments_target[:noteable_type],
- noteable_id: @comments_target[:noteable_id],
- commit_id: @comments_target[:commit_id],
- line_type: line_type,
- line_code: line_code,
- note_type: LegacyDiffNote.name,
- discussion_id: discussion_id
+ line_code: line_code,
+ line_type: line_type,
}
- button_tag(class: 'btn add-diff-note js-add-diff-note-button',
- data: data,
- title: 'Add a comment to this line') do
- icon('comment-o')
+ if use_legacy_diff_note
+ discussion_id = LegacyDiffNote.build_discussion_id(
+ @comments_target[:noteable_type],
+ @comments_target[:noteable_id] || @comments_target[:commit_id],
+ line_code
+ )
+
+ data.merge!(
+ note_type: LegacyDiffNote.name,
+ discussion_id: discussion_id
+ )
+ else
+ discussion_id = DiffNote.build_discussion_id(
+ @comments_target[:noteable_type],
+ @comments_target[:noteable_id] || @comments_target[:commit_id],
+ position
+ )
+
+ data.merge!(
+ position: position.to_json,
+ note_type: DiffNote.name,
+ discussion_id: discussion_id
+ )
end
+
+ data
end
def link_to_reply_discussion(note, line_type = nil)
@@ -60,14 +93,15 @@ module NotesHelper
}
if note.diff_note?
- data.merge!(
- line_code: note.line_code,
- note_type: LegacyDiffNote.name
- )
+ data[:note_type] = note.type
+
+ data.merge!(note.diff_attributes)
end
- button_tag 'Reply...', class: 'btn btn-text-field js-discussion-reply-button',
- data: data, title: 'Add a reply'
+ content_tag(:div, class: "discussion-reply-holder") do
+ button_tag 'Reply...', class: 'btn btn-text-field js-discussion-reply-button',
+ data: data, title: 'Add a reply'
+ end
end
def note_max_access_for_user(note)
@@ -79,4 +113,14 @@ module NotesHelper
full_key = { project: note.project, user_id: note.author_id }
@max_access_by_user_id[full_key]
end
+
+ def diff_note_path(note)
+ return unless note.diff_note?
+
+ if note.for_merge_request? && note.active?
+ diffs_namespace_project_merge_request_path(note.project.namespace, note.project, note.noteable, anchor: note.line_code)
+ elsif note.for_commit?
+ namespace_project_commit_path(note.project.namespace, note.project, note.noteable, anchor: note.line_code)
+ end
+ end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index f312a7ccca3..3bbbb26cff2 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -206,10 +206,14 @@ module ProjectsHelper
end
def default_clone_protocol
- if !current_user || current_user.require_ssh_key?
- gitlab_config.protocol
+ if allowed_protocols_present?
+ enabled_protocol
else
- "ssh"
+ if !current_user || current_user.require_ssh_key?
+ gitlab_config.protocol
+ else
+ 'ssh'
+ end
end
end
@@ -289,7 +293,11 @@ module ProjectsHelper
end
def last_push_event
- if current_user
+ return unless current_user
+
+ if fork = current_user.fork_of(@project)
+ current_user.recent_push(fork.id)
+ else
current_user.recent_push(@project.id)
end
end
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index f9fc525df6f..b165b569372 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -43,15 +43,15 @@ module SearchHelper
# Autocomplete results for internal help pages
def help_autocomplete
[
- { category: "Help", label: "API Help", url: help_page_path("api", "README") },
- { category: "Help", label: "Markdown Help", url: help_page_path("markdown", "markdown") },
- { category: "Help", label: "Permissions Help", url: help_page_path("permissions", "permissions") },
- { category: "Help", label: "Public Access Help", url: help_page_path("public_access", "public_access") },
- { category: "Help", label: "Rake Tasks Help", url: help_page_path("raketasks", "README") },
- { category: "Help", label: "SSH Keys Help", url: help_page_path("ssh", "README") },
- { category: "Help", label: "System Hooks Help", url: help_page_path("system_hooks", "system_hooks") },
- { category: "Help", label: "Webhooks Help", url: help_page_path("web_hooks", "web_hooks") },
- { category: "Help", label: "Workflow Help", url: help_page_path("workflow", "README") },
+ { category: "Help", label: "API Help", url: help_page_path("api/README") },
+ { category: "Help", label: "Markdown Help", url: help_page_path("markdown/markdown") },
+ { category: "Help", label: "Permissions Help", url: help_page_path("permissions/permissions") },
+ { category: "Help", label: "Public Access Help", url: help_page_path("public_access/public_access") },
+ { category: "Help", label: "Rake Tasks Help", url: help_page_path("raketasks/README") },
+ { category: "Help", label: "SSH Keys Help", url: help_page_path("ssh/README") },
+ { category: "Help", label: "System Hooks Help", url: help_page_path("system_hooks/system_hooks") },
+ { category: "Help", label: "Webhooks Help", url: help_page_path("web_hooks/web_hooks") },
+ { category: "Help", label: "Workflow Help", url: help_page_path("workflow/README") },
]
end
diff --git a/app/helpers/time_helper.rb b/app/helpers/time_helper.rb
index b04b0a5114c..8cb82c2d5cc 100644
--- a/app/helpers/time_helper.rb
+++ b/app/helpers/time_helper.rb
@@ -23,4 +23,11 @@ module TimeHelper
def date_from_to(from, to)
"#{from.to_s(:short)} - #{to.to_s(:short)}"
end
+
+ def duration_in_numbers(finished_at, started_at)
+ diff_in_seconds = finished_at.to_i - started_at.to_i
+ time_format = diff_in_seconds < 1.hour ? "%M:%S" : "%H:%M:%S"
+
+ Time.at(diff_in_seconds).utc.strftime(time_format)
+ end
end
diff --git a/app/helpers/workhorse_helper.rb b/app/helpers/workhorse_helper.rb
index 2bd0dbfd095..d887cdadc34 100644
--- a/app/helpers/workhorse_helper.rb
+++ b/app/helpers/workhorse_helper.rb
@@ -1,4 +1,4 @@
-# Helpers to send Git blobs, diffs or archives through Workhorse.
+# Helpers to send Git blobs, diffs, patches or archives through Workhorse.
# Workhorse will also serve files when using `send_file`.
module WorkhorseHelper
# Send a Git blob through Workhorse
@@ -16,9 +16,22 @@ module WorkhorseHelper
head :ok
end
+ # Send a Git patch through Workhorse
+ def send_git_patch(repository, diff_refs)
+ headers.store(*Gitlab::Workhorse.send_git_patch(repository, diff_refs))
+ headers['Content-Disposition'] = 'inline'
+ head :ok
+ end
+
# Archive a Git repository and send it through Workhorse
def send_git_archive(repository, ref:, format:)
headers.store(*Gitlab::Workhorse.send_git_archive(repository, ref: ref, format: format))
head :ok
end
+
+ # Send an entry from artifacts through Workhorse
+ def send_artifacts_entry(build, entry)
+ headers.store(*Gitlab::Workhorse.send_artifacts_entry(build, entry))
+ head :ok
+ end
end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index ba1f2ae4075..eeb0ceba081 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -157,10 +157,11 @@ class Ability
# Push abilities on the users team role
rules.push(*project_team_rules(project.team, user))
- if project.owner == user ||
- (project.group && project.group.has_owner?(user)) ||
- user.admin?
+ owner = user.admin? ||
+ project.owner == user ||
+ (project.group && project.group.has_owner?(user))
+ if owner
rules.push(*project_owner_rules)
end
@@ -169,6 +170,10 @@ class Ability
# Allow to read builds for internal projects
rules << :read_build if project.public_builds?
+
+ unless owner || project.team.member?(user) || project_group_member?(project, user)
+ rules << :request_access
+ end
end
if project.archived?
@@ -345,8 +350,11 @@ class Ability
rules = []
rules << :read_group if can_read_group?(user, group)
+ owner = user.admin? || group.has_owner?(user)
+ master = owner || group.has_master?(user)
+
# Only group masters and group owners can create new projects
- if group.has_master?(user) || group.has_owner?(user) || user.admin?
+ if master
rules += [
:create_projects,
:admin_milestones
@@ -354,7 +362,7 @@ class Ability
end
# Only group owner and administrators can admin group
- if group.has_owner?(user) || user.admin?
+ if owner
rules += [
:admin_group,
:admin_namespace,
@@ -363,6 +371,10 @@ class Ability
]
end
+ if group.public? || (group.internal? && !user.external?)
+ rules << :request_access unless group.users.include?(user)
+ end
+
rules.flatten
end
@@ -564,5 +576,13 @@ class Ability
rules
end
+
+ def project_group_member?(project, user)
+ project.group &&
+ (
+ project.group.members.exists?(user_id: user.id) ||
+ project.group.requesters.exists?(user_id: user.id)
+ )
+ end
end
end
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 5fa6eacd234..c6f77cc055f 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -59,6 +59,9 @@ class ApplicationSetting < ActiveRecord::Base
presence: true,
inclusion: { in: ->(_object) { Gitlab.config.repositories.storages.keys } }
+ validates :enabled_git_access_protocol,
+ inclusion: { in: %w(ssh http), allow_blank: true, allow_nil: true }
+
validates_each :restricted_visibility_levels do |record, attr, value|
unless value.nil?
value.each do |level|
@@ -139,6 +142,7 @@ class ApplicationSetting < ActiveRecord::Base
send_user_confirmation_email: false,
container_registry_token_expire_delay: 5,
repository_storage: 'default',
+ user_default_external: false,
)
end
diff --git a/app/models/award_emoji.rb b/app/models/award_emoji.rb
index 59c7d87f5df..46b17479d6d 100644
--- a/app/models/award_emoji.rb
+++ b/app/models/award_emoji.rb
@@ -8,7 +8,7 @@ class AwardEmoji < ActiveRecord::Base
belongs_to :user
validates :awardable, :user, presence: true
- validates :name, presence: true, inclusion: { in: Emoji.emojis_names }
+ validates :name, presence: true, inclusion: { in: Gitlab::Emoji.emojis_names }
validates :name, uniqueness: { scope: [:user, :awardable_type, :awardable_id] }
participant :user
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 5c973749975..e189dbac285 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -13,6 +13,7 @@ module Ci
scope :ignore_failures, ->() { where(allow_failure: false) }
scope :with_artifacts, ->() { where.not(artifacts_file: nil) }
scope :with_expired_artifacts, ->() { with_artifacts.where('artifacts_expire_at < ?', Time.now) }
+ scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) }
mount_uploader :artifacts_file, ArtifactUploader
mount_uploader :artifacts_metadata, ArtifactUploader
@@ -25,10 +26,6 @@ module Ci
after_create :execute_hooks
class << self
- def last_month
- where('created_at > ?', Date.today - 1.month)
- end
-
def first_pending
pending.unstarted.order('created_at ASC').first
end
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 174ccbaea6c..2ef3973c160 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -214,6 +214,13 @@ class Commit
@raw.short_id(7)
end
+ def diff_refs
+ Gitlab::Diff::DiffRefs.new(
+ base_sha: self.parent_id || self.sha,
+ head_sha: self.sha
+ )
+ end
+
def pipelines
@pipeline ||= project.pipelines.where(sha: sha)
end
diff --git a/app/models/commit_range.rb b/app/models/commit_range.rb
index 4066958f67c..630ee9601e0 100644
--- a/app/models/commit_range.rb
+++ b/app/models/commit_range.rb
@@ -23,7 +23,7 @@ class CommitRange
attr_reader :commit_from, :notation, :commit_to
attr_reader :ref_from, :ref_to
- # Optional Project model
+ # The Project model
attr_accessor :project
# The beginning and ending refs can be named or SHAs, and
@@ -56,7 +56,7 @@ class CommitRange
# Initialize a CommitRange
#
# range_string - The String commit range.
- # project - An optional Project model.
+ # project - The Project model.
#
# Raises ArgumentError if `range_string` does not match `PATTERN`.
def initialize(range_string, project)
diff --git a/app/models/concerns/note_on_diff.rb b/app/models/concerns/note_on_diff.rb
new file mode 100644
index 00000000000..2785fbb21c9
--- /dev/null
+++ b/app/models/concerns/note_on_diff.rb
@@ -0,0 +1,52 @@
+module NoteOnDiff
+ extend ActiveSupport::Concern
+
+ NUMBER_OF_TRUNCATED_DIFF_LINES = 16
+
+ included do
+ delegate :blob, :highlighted_diff_lines, to: :diff_file, allow_nil: true
+ end
+
+ def diff_note?
+ true
+ end
+
+ def diff_file
+ raise NotImplementedError
+ end
+
+ def diff_line
+ raise NotImplementedError
+ end
+
+ def for_line?(line)
+ raise NotImplementedError
+ end
+
+ def diff_attributes
+ raise NotImplementedError
+ end
+
+ def can_be_award_emoji?
+ false
+ end
+
+ # Returns an array of at most 16 highlighted lines above a diff note
+ def truncated_diff_lines
+ prev_lines = []
+
+ highlighted_diff_lines.each do |line|
+ if line.meta?
+ prev_lines.clear
+ else
+ prev_lines << line
+
+ break if for_line?(line)
+
+ prev_lines.shift if prev_lines.length >= NUMBER_OF_TRUNCATED_DIFF_LINES
+ end
+ end
+
+ prev_lines
+ end
+end
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index e498ca96e3c..520026c18dd 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -11,6 +11,8 @@ class Deployment < ActiveRecord::Base
delegate :name, to: :environment, prefix: true
+ after_save :keep_around_commit
+
def commit
project.commit(sha)
end
@@ -26,4 +28,8 @@ class Deployment < ActiveRecord::Base
def last?
self == environment.last_deployment
end
+
+ def keep_around_commit
+ project.repository.keep_around(self.sha)
+ end
end
diff --git a/app/models/diff_note.rb b/app/models/diff_note.rb
new file mode 100644
index 00000000000..9671955db36
--- /dev/null
+++ b/app/models/diff_note.rb
@@ -0,0 +1,127 @@
+class DiffNote < Note
+ include NoteOnDiff
+
+ serialize :original_position, Gitlab::Diff::Position
+ serialize :position, Gitlab::Diff::Position
+
+ validates :original_position, presence: true
+ validates :position, presence: true
+ validates :diff_line, presence: true
+ validates :line_code, presence: true, line_code: true
+ validates :noteable_type, inclusion: { in: ['Commit', 'MergeRequest'] }
+ validate :positions_complete
+ validate :verify_supported
+
+ before_validation :set_original_position, :update_position, on: :create
+ before_validation :set_line_code
+ after_save :keep_around_commits
+
+ class << self
+ def build_discussion_id(noteable_type, noteable_id, position)
+ [super(noteable_type, noteable_id), *position.key].join("-")
+ end
+ end
+
+ def new_diff_note?
+ true
+ end
+
+ def diff_attributes
+ { position: position.to_json }
+ end
+
+ def discussion_id
+ @discussion_id ||= self.class.build_discussion_id(noteable_type, noteable_id || commit_id, position)
+ end
+
+ def original_discussion_id
+ @original_discussion_id ||= self.class.build_discussion_id(noteable_type, noteable_id || commit_id, original_position)
+ end
+
+ def position=(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
+
+ super(new_position)
+ end
+
+ def diff_file
+ @diff_file ||= self.original_position.diff_file(self.project.repository)
+ end
+
+ def diff_line
+ @diff_line ||= diff_file.line_for_position(self.original_position) if diff_file
+ end
+
+ def for_line?(line)
+ diff_file.position(line) == self.original_position
+ end
+
+ def active?(diff_refs = nil)
+ return false unless supported?
+ return true if for_commit?
+
+ diff_refs ||= self.noteable.diff_refs
+
+ self.position.diff_refs == diff_refs
+ end
+
+ private
+
+ def supported?
+ !self.for_merge_request? || self.noteable.support_new_diff_notes?
+ end
+
+ def set_original_position
+ self.original_position = self.position.dup
+ 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?
+
+ Notes::DiffPositionUpdateService.new(
+ self.project,
+ nil,
+ old_diff_refs: self.position.diff_refs,
+ new_diff_refs: self.noteable.diff_refs,
+ paths: self.position.paths
+ ).execute(self)
+ end
+
+ def verify_supported
+ return if supported?
+
+ errors.add(:noteable, "doesn't support new-style diff notes")
+ end
+
+ def positions_complete
+ return if self.original_position.complete? && self.position.complete?
+
+ errors.add(:position, "is invalid")
+ end
+
+ def keep_around_commits
+ project.repository.keep_around(self.original_position.base_sha)
+ project.repository.keep_around(self.original_position.start_sha)
+ project.repository.keep_around(self.original_position.head_sha)
+
+ if self.position != self.original_position
+ project.repository.keep_around(self.position.base_sha)
+ project.repository.keep_around(self.position.start_sha)
+ project.repository.keep_around(self.position.head_sha)
+ end
+ end
+end
diff --git a/app/models/event.rb b/app/models/event.rb
index d7d23c7ae6d..fd736d12359 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -67,7 +67,7 @@ class Event < ActiveRecord::Base
elsif issue? || issue_note?
Ability.abilities.allowed?(user, :read_issue, note? ? note_target : target)
else
- ((merge_request? || note?) && target) || milestone?
+ ((merge_request? || note?) && target.present?) || milestone?
end
end
@@ -136,7 +136,7 @@ class Event < ActiveRecord::Base
end
def note?
- target_type == "Note"
+ target.is_a?(Note)
end
def issue?
diff --git a/app/models/group.rb b/app/models/group.rb
index a8be7004ee8..37631b99701 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -90,7 +90,7 @@ class Group < Namespace
end
def avatar_url(size = nil)
- if avatar.present?
+ if self[:avatar].present?
[gitlab_config.url, avatar.url].join
end
end
diff --git a/app/models/label.rb b/app/models/label.rb
index 49c352cc239..dc5586f5756 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -20,10 +20,10 @@ class Label < ActiveRecord::Base
validates :color, color: true, allow_blank: false
validates :project, presence: true, unless: Proc.new { |service| service.template? }
- # Don't allow '?', '&', and ',' for label titles
+ # Don't allow ',' for label titles
validates :title,
presence: true,
- format: { with: /\A[^&\?,]+\z/ },
+ format: { with: /\A[^,]+\z/ },
uniqueness: { scope: :project_id }
before_save :nullify_priority
@@ -58,8 +58,8 @@ class Label < ActiveRecord::Base
(?:
(?<label_id>\d+) | # Integer-based label ID, or
(?<label_name>
- [A-Za-z0-9_-]+ | # String-based single-word label title, or
- "[^&\?,]+" # String-based multi-word label surrounded in quotes
+ [A-Za-z0-9_\-\?&]+ | # String-based single-word label title, or
+ "[^,]+" # String-based multi-word label surrounded in quotes
)
)
}x
@@ -114,7 +114,7 @@ class Label < ActiveRecord::Base
end
def title=(value)
- write_attribute(:title, Sanitize.clean(value.to_s)) if value.present?
+ write_attribute(:title, sanitize_title(value)) if value.present?
end
private
@@ -132,4 +132,8 @@ class Label < ActiveRecord::Base
def nullify_priority
self.priority = nil if priority.blank?
end
+
+ def sanitize_title(value)
+ CGI.unescapeHTML(Sanitize.clean(value.to_s))
+ end
end
diff --git a/app/models/legacy_diff_note.rb b/app/models/legacy_diff_note.rb
index 33d2a69ebaf..790dfd4d480 100644
--- a/app/models/legacy_diff_note.rb
+++ b/app/models/legacy_diff_note.rb
@@ -1,4 +1,6 @@
class LegacyDiffNote < Note
+ include NoteOnDiff
+
serialize :st_diff
validates :line_code, presence: true, line_code: true
@@ -11,12 +13,12 @@ class LegacyDiffNote < Note
end
end
- def diff_note?
+ def legacy_diff_note?
true
end
- def legacy_diff_note?
- true
+ def diff_attributes
+ { line_code: line_code }
end
def discussion_id
@@ -27,61 +29,20 @@ class LegacyDiffNote < Note
line_code.split('_')[0] if line_code
end
- def diff_old_line
- line_code.split('_')[1].to_i if line_code
- end
-
- def diff_new_line
- line_code.split('_')[2].to_i if line_code
- end
-
def diff
@diff ||= Gitlab::Git::Diff.new(st_diff) if st_diff.respond_to?(:map)
end
- def diff_file_path
- diff.new_path.presence || diff.old_path
- end
-
- def diff_lines
- @diff_lines ||= Gitlab::Diff::Parser.new.parse(diff.diff.each_line)
+ def diff_file
+ @diff_file ||= Gitlab::Diff::File.new(diff, repository: self.project.repository) if diff
end
def diff_line
- @diff_line ||= diff_lines.find { |line| generate_line_code(line) == self.line_code }
+ @diff_line ||= diff_file.line_for_line_code(self.line_code)
end
- def diff_line_text
- diff_line.try(:text)
- end
-
- def diff_line_type
- diff_line.try(:type)
- end
-
- def highlighted_diff_lines
- Gitlab::Diff::Highlight.new(diff_lines).highlight
- end
-
- def truncated_diff_lines
- max_number_of_lines = 16
- prev_match_line = nil
- prev_lines = []
-
- highlighted_diff_lines.each do |line|
- if line.type == "match"
- prev_lines.clear
- prev_match_line = line
- else
- prev_lines << line
-
- break if generate_line_code(line) == self.line_code
-
- prev_lines.shift if prev_lines.length >= max_number_of_lines
- end
- end
-
- prev_lines
+ def for_line?(line)
+ !line.meta? && diff_file.line_code(line) == self.line_code
end
# Check if this note is part of an "active" discussion
@@ -102,7 +63,7 @@ class LegacyDiffNote < Note
if noteable_diff
parsed_lines = Gitlab::Diff::Parser.new.parse(noteable_diff.diff.each_line)
- @active = parsed_lines.any? { |line_obj| line_obj.text == diff_line_text }
+ @active = parsed_lines.any? { |line_obj| line_obj.text == diff_line.text }
else
@active = false
end
@@ -110,10 +71,6 @@ class LegacyDiffNote < Note
@active
end
- def award_emoji_supported?
- false
- end
-
private
def find_diff
@@ -149,10 +106,6 @@ class LegacyDiffNote < Note
self.class.where(attributes).last.try(:diff)
end
- def generate_line_code(line)
- Gitlab::Diff::LineCode.generate(diff_file_path, line.new_pos, line.old_pos)
- end
-
# Find the diff on noteable that matches our own
def find_noteable_diff
diffs = noteable.diffs(Commit.max_diff_options)
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index cb0f871897a..157901378d3 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -16,10 +16,10 @@ class MergeRequest < ActiveRecord::Base
serialize :merge_params, Hash
- after_create :create_merge_request_diff, unless: :importing
+ after_create :create_merge_request_diff, unless: :importing?
after_update :update_merge_request_diff
- delegate :commits, :diffs, :real_size, to: :merge_request_diff, prefix: nil
+ delegate :commits, :real_size, to: :merge_request_diff, prefix: nil
# When this attribute is true some MR validation is ignored
# It allows us to close or modify broken merge requests
@@ -29,10 +29,6 @@ class MergeRequest < ActiveRecord::Base
# when creating new merge request
attr_accessor :can_be_created, :compare_commits, :compare
- # Temporary fields to store target_sha, and base_sha to
- # compare when importing pull requests from GitHub
- attr_accessor :base_target_sha, :head_source_sha
-
state_machine :state, initial: :opened do
event :close do
transition [:reopened, :opened] => :closed
@@ -89,12 +85,7 @@ class MergeRequest < ActiveRecord::Base
state :cannot_be_merged
around_transition do |merge_request, transition, block|
- merge_request.record_timestamps = false
- begin
- block.call
- ensure
- merge_request.record_timestamps = true
- end
+ Gitlab::Timeless.timeless(merge_request, &block)
end
end
@@ -169,28 +160,99 @@ class MergeRequest < ActiveRecord::Base
reference
end
- def last_commit
- merge_request_diff ? merge_request_diff.last_commit : compare_commits.last
- end
-
def first_commit
merge_request_diff ? merge_request_diff.first_commit : compare_commits.first
end
+ def diffs(*args)
+ merge_request_diff ? merge_request_diff.diffs(*args) : compare.diffs(*args)
+ end
+
def diff_size
merge_request_diff.size
end
def diff_base_commit
- if merge_request_diff
+ if persisted?
merge_request_diff.base_commit
- elsif source_sha
- self.target_project.merge_base_commit(self.source_sha, self.target_branch)
+ elsif diff_start_commit && diff_head_commit
+ self.target_project.merge_base_commit(diff_start_sha, diff_head_sha)
+ end
+ end
+
+ # MRs created before 8.4 don't store a MergeRequestDiff#base_commit_sha,
+ # but we need to get a commit for the "View file @ ..." link by deleted files,
+ # so we find the likely one if we can't get the actual one.
+ # This will not be the actual base commit if the target branch was merged into
+ # the source branch after the merge request was created, but it is good enough
+ # for the specific purpose of linking to a commit.
+ # It is not good enough for use in `Gitlab::Git::DiffRefs`, which needs the
+ # true base commit, so we can't simply have `#diff_base_commit` fall back on
+ # this method.
+ def likely_diff_base_commit
+ first_commit.parent || first_commit
+ end
+
+ def diff_start_commit
+ if persisted?
+ merge_request_diff.start_commit
+ else
+ target_branch_head
+ end
+ end
+
+ def diff_head_commit
+ if persisted?
+ merge_request_diff.head_commit
+ else
+ source_branch_head
end
end
- def last_commit_short_sha
- last_commit.short_id
+ def diff_start_sha
+ diff_start_commit.try(:sha)
+ end
+
+ def diff_base_sha
+ diff_base_commit.try(:sha)
+ end
+
+ def diff_head_sha
+ diff_head_commit.try(:sha)
+ end
+
+ # When importing a pull request from GitHub, the old and new branches may no
+ # longer actually exist by those names, but we need to recreate the merge
+ # request diff with the right source and target shas.
+ # We use these attributes to force these to the intended values.
+ attr_writer :target_branch_sha, :source_branch_sha
+
+ def source_branch_head
+ source_branch_ref = @source_branch_sha || source_branch
+ source_project.repository.commit(source_branch) if source_branch_ref
+ end
+
+ def target_branch_head
+ target_branch_ref = @target_branch_sha || target_branch
+ target_project.repository.commit(target_branch) if target_branch_ref
+ end
+
+ def target_branch_sha
+ target_branch_head.try(:sha)
+ end
+
+ def source_branch_sha
+ source_branch_head.try(:sha)
+ end
+
+ def diff_refs
+ return unless diff_start_commit || diff_base_commit
+
+ Gitlab::Diff::DiffRefs.new(
+ base_sha: diff_base_sha,
+ start_sha: diff_start_sha,
+ head_sha: diff_head_sha
+ )
end
def validate_branches
@@ -227,21 +289,30 @@ class MergeRequest < ActiveRecord::Base
def update_merge_request_diff
if source_branch_changed? || target_branch_changed?
- reload_code
+ reload_diff
end
end
- def reload_code
- if merge_request_diff && open?
- merge_request_diff.reload_content
- end
+ def reload_diff
+ return unless merge_request_diff && open?
+
+ old_diff_refs = self.diff_refs
+
+ merge_request_diff.reload_content
+
+ new_diff_refs = self.diff_refs
+
+ update_diff_notes_positions(
+ old_diff_refs: old_diff_refs,
+ new_diff_refs: new_diff_refs
+ )
end
def check_if_can_be_merged
return unless unchecked?
can_be_merged =
- !broken? && project.repository.can_be_merged?(source_sha, target_branch)
+ !broken? && project.repository.can_be_merged?(diff_head_sha, target_branch)
if can_be_merged
mark_as_mergeable
@@ -251,11 +322,11 @@ class MergeRequest < ActiveRecord::Base
end
def merge_event
- self.target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::MERGED).last
+ @merge_event ||= target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::MERGED).last
end
def closed_event
- self.target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::CLOSED).last
+ @closed_event ||= target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::CLOSED).last
end
WIP_REGEX = /\A\s*(\[WIP\]\s*|WIP:\s*|WIP\s+)+\s*/i.freeze
@@ -293,7 +364,7 @@ class MergeRequest < ActiveRecord::Base
!source_project.protected_branch?(source_branch) &&
!source_project.root_ref?(source_branch) &&
Ability.abilities.allowed?(current_user, :push_code, source_project) &&
- last_commit == source_project.commit(source_branch)
+ diff_head_commit == source_branch_head
end
def should_remove_source_branch?
@@ -331,8 +402,8 @@ class MergeRequest < ActiveRecord::Base
work_in_progress: work_in_progress?
}
- if last_commit
- attrs.merge!(last_commit: last_commit.hook_attrs)
+ if diff_head_commit
+ attrs.merge!(last_commit: diff_head_commit.hook_attrs)
end
attributes.merge!(attrs)
@@ -481,7 +552,7 @@ class MergeRequest < ActiveRecord::Base
end
def can_be_merged_by?(user)
- ::Gitlab::GitAccess.new(user, project).can_push_to_branch?(target_branch)
+ ::Gitlab::GitAccess.new(user, project, 'web').can_push_to_branch?(target_branch)
end
def mergeable_ci_state?
@@ -510,22 +581,6 @@ class MergeRequest < ActiveRecord::Base
end
end
- def target_sha
- return @base_target_sha if defined?(@base_target_sha)
-
- target_project.repository.commit(target_branch).try(:sha)
- end
-
- def source_sha
- return @head_source_sha if defined?(@head_source_sha)
-
- last_commit.try(:sha) || source_tip.try(:sha)
- end
-
- def source_tip
- source_branch && source_project.repository.commit(source_branch)
- end
-
def fetch_ref
target_project.repository.fetch_ref(
source_project.repository.path_to_repo,
@@ -558,10 +613,10 @@ class MergeRequest < ActiveRecord::Base
def diverged_commits_count
cache = Rails.cache.read(:"merge_request_#{id}_diverged_commits")
- if cache.blank? || cache[:source_sha] != source_sha || cache[:target_sha] != target_sha
+ if cache.blank? || cache[:source_sha] != source_branch_sha || cache[:target_sha] != target_branch_sha
cache = {
- source_sha: source_sha,
- target_sha: target_sha,
+ source_sha: source_branch_sha,
+ target_sha: target_branch_sha,
diverged_commits_count: compute_diverged_commits_count
}
Rails.cache.write(:"merge_request_#{id}_diverged_commits", cache)
@@ -571,9 +626,9 @@ class MergeRequest < ActiveRecord::Base
end
def compute_diverged_commits_count
- return 0 unless source_sha && target_sha
+ return 0 unless source_branch_sha && target_branch_sha
- Gitlab::Git::Commit.between(target_project.repository.raw_repository, source_sha, target_sha).size
+ Gitlab::Git::Commit.between(target_project.repository.raw_repository, source_branch_sha, target_branch_sha).size
end
private :compute_diverged_commits_count
@@ -582,13 +637,7 @@ class MergeRequest < ActiveRecord::Base
end
def pipeline
- @pipeline ||= source_project.pipeline(last_commit.id, source_branch) if last_commit && source_project
- end
-
- def diff_refs
- return nil unless diff_base_commit
-
- [diff_base_commit, last_commit]
+ @pipeline ||= source_project.pipeline(diff_head_sha, source_branch) if diff_head_sha && source_project
end
def merge_commit
@@ -603,6 +652,36 @@ class MergeRequest < ActiveRecord::Base
merge_commit
end
+ def support_new_diff_notes?
+ diff_refs && diff_refs.complete?
+ end
+
+ def update_diff_notes_positions(old_diff_refs:, new_diff_refs:)
+ return unless support_new_diff_notes?
+ return if new_diff_refs == old_diff_refs
+
+ active_diff_notes = self.notes.diff_notes.select do |note|
+ note.new_diff_note? && note.active?(old_diff_refs)
+ end
+
+ return if active_diff_notes.empty?
+
+ paths = active_diff_notes.flat_map { |n| n.diff_file.paths }.uniq
+
+ service = Notes::DiffPositionUpdateService.new(
+ self.project,
+ nil,
+ old_diff_refs: old_diff_refs,
+ new_diff_refs: new_diff_refs,
+ paths: paths
+ )
+
+ active_diff_notes.each do |note|
+ service.execute(note)
+ Gitlab::Timeless.timeless(note, &:save)
+ end
+ end
+
def keep_around_commit
project.repository.keep_around(self.merge_commit_sha)
end
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index 0fcde6fc8f1..feaba925bad 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -7,7 +7,7 @@ class MergeRequestDiff < ActiveRecord::Base
belongs_to :merge_request
- delegate :head_source_sha, :target_branch, :source_branch, to: :merge_request, prefix: nil
+ delegate :source_branch_sha, :target_branch_sha, :target_branch, :source_branch, to: :merge_request, prefix: nil
state_machine :state, initial: :empty do
state :collected
@@ -24,7 +24,7 @@ class MergeRequestDiff < ActiveRecord::Base
serialize :st_diffs
after_create :reload_content, unless: :importing?
- after_save :keep_around_commit
+ after_save :keep_around_commits, unless: :importing?
def reload_content
reload_commits
@@ -39,14 +39,15 @@ class MergeRequestDiff < ActiveRecord::Base
if options[:ignore_whitespace_change]
@diffs_no_whitespace ||= begin
compare = Gitlab::Git::Compare.new(
- self.repository.raw_repository,
- self.base,
- self.head,
+ repository.raw_repository,
+ self.start_commit_sha || self.target_branch_sha,
+ self.head_commit_sha || self.source_branch_sha,
)
compare.diffs(options)
end
else
- @diffs ||= load_diffs(st_diffs, options)
+ @diffs ||= {}
+ @diffs[options] ||= load_diffs(st_diffs, options)
end
end
@@ -63,37 +64,39 @@ class MergeRequestDiff < ActiveRecord::Base
end
def base_commit
- return nil unless self.base_commit_sha
+ return unless self.base_commit_sha
- merge_request.target_project.commit(self.base_commit_sha)
+ project.commit(self.base_commit_sha)
end
- def last_commit_short_sha
- @last_commit_short_sha ||= last_commit.short_id
- end
+ def start_commit
+ return unless self.start_commit_sha
- def dump_commits(commits)
- commits.map(&:to_hash)
+ project.commit(self.start_commit_sha)
end
- def load_commits(array)
- array.map { |hash| Commit.new(Gitlab::Git::Commit.new(hash), merge_request.source_project) }
- end
+ def head_commit
+ return last_commit unless self.head_commit_sha
- def dump_diffs(diffs)
- if diffs.respond_to?(:map)
- diffs.map(&:to_hash)
- end
+ project.commit(self.head_commit_sha)
end
- def load_diffs(raw, options)
- if raw.respond_to?(:each)
- Gitlab::Git::DiffCollection.new(raw, options)
- else
- Gitlab::Git::DiffCollection.new([])
- end
+ def compare
+ @compare ||=
+ begin
+ # Update ref for merge request
+ merge_request.fetch_ref
+
+ Gitlab::Git::Compare.new(
+ repository.raw_repository,
+ self.target_branch_sha,
+ self.source_branch_sha
+ )
+ end
end
+ private
+
# Collect array of Git::Commit objects
# between target and source branches
def unmerged_commits
@@ -106,6 +109,14 @@ class MergeRequestDiff < ActiveRecord::Base
commits
end
+ def dump_commits(commits)
+ commits.map(&:to_hash)
+ end
+
+ def load_commits(array)
+ array.map { |hash| Commit.new(Gitlab::Git::Commit.new(hash), merge_request.source_project) }
+ end
+
# Reload all commits related to current merge request from repo
# and save it as array of hashes in st_commits db field
def reload_commits
@@ -120,6 +131,32 @@ class MergeRequestDiff < ActiveRecord::Base
update_columns_serialized(new_attributes)
end
+ # Collect array of Git::Diff objects
+ # between target and source branches
+ def unmerged_diffs
+ compare.diffs(Commit.max_diff_options)
+ end
+
+ def dump_diffs(diffs)
+ if diffs.respond_to?(:map)
+ diffs.map(&:to_hash)
+ end
+ end
+
+ def load_diffs(raw, options)
+ if raw.respond_to?(:each)
+ if paths = options[:paths]
+ raw = raw.select do |diff|
+ paths.include?(diff[:old_path]) || paths.include?(diff[:new_path])
+ end
+ end
+
+ Gitlab::Git::DiffCollection.new(raw, options)
+ else
+ Gitlab::Git::DiffCollection.new([])
+ end
+ end
+
# Reload diffs between branches related to current merge request from repo
# and save it as array of hashes in st_diffs db field
def reload_diffs
@@ -147,59 +184,33 @@ class MergeRequestDiff < ActiveRecord::Base
new_attributes[:st_diffs] = new_diffs
- base_commit_sha = self.repository.merge_base(self.head, self.base)
- new_attributes[:base_commit_sha] = base_commit_sha
-
- self.repository.keep_around(base_commit_sha)
+ new_attributes[:start_commit_sha] = self.target_branch_sha
+ new_attributes[:head_commit_sha] = self.source_branch_sha
+ new_attributes[:base_commit_sha] = branch_base_sha
update_columns_serialized(new_attributes)
- end
-
- # Collect array of Git::Diff objects
- # between target and source branches
- def unmerged_diffs
- compare.diffs(Commit.max_diff_options)
- end
- def repository
- merge_request.target_project.repository
+ keep_around_commits
end
- def source_sha
- return head_source_sha if head_source_sha.present?
-
- source_commit = merge_request.source_project.commit(source_branch)
- source_commit.try(:sha)
+ def project
+ merge_request.target_project
end
- def target_sha
- merge_request.target_sha
+ def repository
+ project.repository
end
- def base
- self.target_sha || self.target_branch
- end
+ def branch_base_commit
+ return unless self.source_branch_sha && self.target_branch_sha
- def head
- self.source_sha
+ project.merge_base_commit(self.source_branch_sha, self.target_branch_sha)
end
- def compare
- @compare ||=
- begin
- # Update ref for merge request
- merge_request.fetch_ref
-
- Gitlab::Git::Compare.new(
- self.repository.raw_repository,
- self.base,
- self.head
- )
- end
+ def branch_base_sha
+ branch_base_commit.try(:sha)
end
- private
-
#
# #save or #update_attributes providing changes on serialized attributes do a lot of
# serialization and deserialization calls resulting in bad performance.
@@ -223,7 +234,9 @@ class MergeRequestDiff < ActiveRecord::Base
reload
end
- def keep_around_commit
- self.repository.keep_around(self.base_commit_sha)
+ def keep_around_commits
+ repository.keep_around(target_branch_sha)
+ repository.keep_around(source_branch_sha)
+ repository.keep_around(branch_base_sha)
end
end
diff --git a/app/models/note.rb b/app/models/note.rb
index 81b5c47b738..8dca2ef09a8 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -10,6 +10,10 @@ class Note < ActiveRecord::Base
# Banzai::ObjectRenderer.
attr_accessor :note_html
+ # An Array containing the number of visible references as generated by
+ # Banzai::ObjectRenderer
+ attr_accessor :user_visible_reference_count
+
default_value_for :system, false
attr_mentionable :note, pipeline: :note
@@ -56,7 +60,7 @@ class Note < ActiveRecord::Base
scope :inc_author, ->{ includes(:author) }
scope :inc_author_project_award_emoji, ->{ includes(:project, :author, :award_emoji) }
- scope :legacy_diff_notes, ->{ where(type: 'LegacyDiffNote') }
+ scope :diff_notes, ->{ where(type: ['LegacyDiffNote', 'DiffNote']) }
scope :non_diff_notes, ->{ where(type: ['Note', nil]) }
scope :with_associations, -> do
@@ -82,7 +86,7 @@ class Note < ActiveRecord::Base
end
def grouped_diff_notes
- legacy_diff_notes.select(&:active?).sort_by(&:created_at).group_by(&:line_code)
+ diff_notes.select(&:active?).sort_by(&:created_at).group_by(&:line_code)
end
# Searches for notes matching the given query.
@@ -115,6 +119,10 @@ class Note < ActiveRecord::Base
false
end
+ def new_diff_note?
+ false
+ end
+
def active?
true
end
@@ -189,11 +197,19 @@ class Note < ActiveRecord::Base
end
def cross_reference_not_visible_for?(user)
- cross_reference? && referenced_mentionables(user).empty?
+ 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
end
def award_emoji?
- award_emoji_supported? && contains_emoji_only?
+ can_be_award_emoji? && contains_emoji_only?
end
def emoji_awardable?
@@ -204,7 +220,7 @@ class Note < ActiveRecord::Base
self.line_code = nil if self.line_code.blank?
end
- def award_emoji_supported?
+ def can_be_award_emoji?
noteable.is_a?(Awardable)
end
diff --git a/app/models/notification_setting.rb b/app/models/notification_setting.rb
index d41fc7073c6..121b598b8f3 100644
--- a/app/models/notification_setting.rb
+++ b/app/models/notification_setting.rb
@@ -5,6 +5,7 @@ class NotificationSetting < ActiveRecord::Base
belongs_to :user
belongs_to :source, polymorphic: true
+ belongs_to :project, foreign_key: 'source_id'
validates :user, presence: true
validates :level, presence: true
@@ -13,7 +14,13 @@ class NotificationSetting < ActiveRecord::Base
allow_nil: true }
scope :for_groups, -> { where(source_type: 'Namespace') }
- scope :for_projects, -> { where(source_type: 'Project') }
+
+ # Exclude projects not included by the Project model's default scope (those that are
+ # pending delete).
+ #
+ scope :for_projects, -> do
+ includes(:project).references(:projects).where(source_type: 'Project').where.not(projects: { id: nil })
+ end
EMAIL_EVENTS = [
:new_note,
diff --git a/app/models/project.rb b/app/models/project.rb
index ae96f00a705..a66b750cd48 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -162,9 +162,7 @@ class Project < ActiveRecord::Base
validates :namespace, presence: true
validates_uniqueness_of :name, scope: :namespace_id
validates_uniqueness_of :path, scope: :namespace_id
- validates :import_url,
- url: { protocols: %w(ssh git http https) },
- if: :external_import?
+ validates :import_url, addressable_url: true, if: :external_import?
validates :star_count, numericality: { greater_than_or_equal_to: 0 }
validate :check_limit, on: :create
validate :avatar_type,
@@ -427,8 +425,8 @@ class Project < ActiveRecord::Base
container_registry_repository.tags.any?
end
- def commit(id = 'HEAD')
- repository.commit(id)
+ def commit(ref = 'HEAD')
+ repository.commit(ref)
end
def merge_base_commit(first_commit_id, second_commit_id)
@@ -463,6 +461,8 @@ class Project < ActiveRecord::Base
end
def import_url=(value)
+ return super(value) unless Gitlab::UrlSanitizer.valid?(value)
+
import_url = Gitlab::UrlSanitizer.new(value)
create_or_update_import_data(credentials: import_url.credentials)
super(import_url.sanitized_url)
@@ -701,7 +701,7 @@ class Project < ActiveRecord::Base
end
def avatar_url
- if avatar.present?
+ if self[:avatar].present?
[gitlab_config.url, avatar.url].join
elsif avatar_in_git
Gitlab::Routing.url_helpers.namespace_project_avatar_url(namespace, self)
@@ -802,18 +802,12 @@ class Project < ActiveRecord::Base
@repo_exists = false
end
+ # Branches that are not _exactly_ matched by a protected branch.
def open_branches
- # We're using a Set here as checking values in a large Set is faster than
- # checking values in a large Array.
- protected_set = Set.new(protected_branch_names)
-
- repository.branches.reject do |branch|
- protected_set.include?(branch.name)
- end
- end
-
- def protected_branch_names
- @protected_branch_names ||= protected_branches.pluck(:name)
+ exact_protected_branch_names = protected_branches.reject(&:wildcard?).map(&:name)
+ branch_names = repository.branches.map(&:name)
+ non_open_branch_names = Set.new(exact_protected_branch_names).intersection(Set.new(branch_names))
+ repository.branches.reject { |branch| non_open_branch_names.include? branch.name }
end
def root_ref?(branch)
@@ -830,11 +824,12 @@ class Project < ActiveRecord::Base
# Check if current branch name is marked as protected in the system
def protected_branch?(branch_name)
- protected_branch_names.include?(branch_name)
+ @protected_branches ||= self.protected_branches.to_a
+ ProtectedBranch.matching(branch_name, protected_branches: @protected_branches).present?
end
def developers_can_push_to_protected_branch?(branch_name)
- protected_branches.any? { |pb| pb.name == branch_name && pb.developers_can_push }
+ protected_branches.matching(branch_name).any?(&:developers_can_push)
end
def forked?
diff --git a/app/models/project_services/irker_service.rb b/app/models/project_services/irker_service.rb
index 58cb720c3c1..ce7d1c5d5b1 100644
--- a/app/models/project_services/irker_service.rb
+++ b/app/models/project_services/irker_service.rb
@@ -112,15 +112,7 @@ class IrkerService < Service
# Authorize both irc://domain.com/#chan and irc://domain.com/chan
if uri.is_a?(URI) && uri.scheme[/^ircs?\z/] && !uri.path.nil?
- # Do not authorize irc://domain.com/
- if uri.fragment.nil? && uri.path.length > 1
- uri.to_s
- else
- # Authorize irc://domain.com/smthg#chan
- # The irker daemon will deal with it by concatenating smthg and
- # chan, thus sending messages on #smthgchan
- uri.to_s
- end
+ uri.to_s
end
end
end
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
index 27bf08bf7d9..97bcbacf2b9 100644
--- a/app/models/project_services/jira_service.rb
+++ b/app/models/project_services/jira_service.rb
@@ -144,7 +144,7 @@ class JiraService < IssueTrackerService
commit_id = if entity.is_a?(Commit)
entity.id
elsif entity.is_a?(MergeRequest)
- entity.last_commit.id
+ entity.diff_head_sha
end
commit_url = build_entity_url(:commit, commit_id)
diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
index 33cf046fa75..b7011d7afdf 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -8,4 +8,51 @@ class ProtectedBranch < ActiveRecord::Base
def commit
project.commit(self.name)
end
+
+ # Returns all protected branches that match the given branch name.
+ # This realizes all records from the scope built up so far, and does
+ # _not_ return a relation.
+ #
+ # This method optionally takes in a list of `protected_branches` to search
+ # through, to avoid calling out to the database.
+ def self.matching(branch_name, protected_branches: nil)
+ (protected_branches || all).select { |protected_branch| protected_branch.matches?(branch_name) }
+ end
+
+ # Returns all branches (among the given list of branches [`Gitlab::Git::Branch`])
+ # that match the current protected branch.
+ def matching(branches)
+ branches.select { |branch| self.matches?(branch.name) }
+ end
+
+ # Checks if the protected branch matches the given branch name.
+ def matches?(branch_name)
+ return false if self.name.blank?
+
+ exact_match?(branch_name) || wildcard_match?(branch_name)
+ end
+
+ # Checks if this protected branch contains a wildcard
+ def wildcard?
+ self.name && self.name.include?('*')
+ end
+
+ protected
+
+ def exact_match?(branch_name)
+ self.name == branch_name
+ end
+
+ def wildcard_match?(branch_name)
+ wildcard_regex === branch_name
+ end
+
+ def wildcard_regex
+ @wildcard_regex ||= begin
+ name = self.name.gsub('*', 'STAR_DONT_ESCAPE')
+ quoted_name = Regexp.quote(name)
+ regex_string = quoted_name.gsub('STAR_DONT_ESCAPE', '.*?')
+ /\A#{regex_string}\z/
+ end
+ end
end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 078ca8f4e13..5b670cb4b8f 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -78,9 +78,9 @@ class Repository
end
end
- def commit(id = 'HEAD')
+ def commit(ref = 'HEAD')
return nil unless exists?
- commit = Gitlab::Git::Commit.find(raw_repository, id)
+ commit = Gitlab::Git::Commit.find(raw_repository, ref)
commit = ::Commit.new(commit, @project) if commit
commit
rescue Rugged::OdbError
@@ -653,16 +653,6 @@ class Repository
end
end
- def blob_for_diff(commit, diff)
- blob_at(commit.id, diff.file_path)
- end
-
- def prev_blob_for_diff(commit, diff)
- if commit.parent_id
- blob_at(commit.parent_id, diff.old_path)
- end
- end
-
def refs_contains_sha(ref_type, sha)
args = %W(#{Gitlab.config.git.bin_path} #{ref_type} --contains #{sha})
names = Gitlab::Popen.popen(args, path_to_repo).first
@@ -911,7 +901,7 @@ class Repository
if line =~ /^.*:.*:\d+:/
ref, filename, startline = line.split(':')
startline = startline.to_i - index
- extname = File.extname(filename)
+ extname = Regexp.escape(File.extname(filename))
basename = filename.sub(/#{extname}$/, '')
break
end
diff --git a/app/models/sent_notification.rb b/app/models/sent_notification.rb
index a2df899d012..f4bcb49b34d 100644
--- a/app/models/sent_notification.rb
+++ b/app/models/sent_notification.rb
@@ -1,4 +1,6 @@
class SentNotification < ActiveRecord::Base
+ serialize :position, Gitlab::Diff::Position
+
belongs_to :project
belongs_to :noteable, polymorphic: true
belongs_to :recipient, class_name: "User"
@@ -7,7 +9,7 @@ class SentNotification < ActiveRecord::Base
validates :reply_key, uniqueness: true
validates :noteable_id, presence: true, unless: :for_commit?
validates :commit_id, presence: true, if: :for_commit?
- validates :line_code, line_code: true, allow_blank: true
+ validate :note_valid
after_save :keep_around_commit
@@ -20,7 +22,7 @@ class SentNotification < ActiveRecord::Base
find_by(reply_key: reply_key)
end
- def record(noteable, recipient_id, reply_key, params = {})
+ def record(noteable, recipient_id, reply_key, attrs = {})
return unless reply_key
noteable_id = nil
@@ -31,7 +33,7 @@ class SentNotification < ActiveRecord::Base
noteable_id = noteable.id
end
- params.reverse_merge!(
+ attrs.reverse_merge!(
project: noteable.project,
noteable_type: noteable.class.name,
noteable_id: noteable_id,
@@ -40,13 +42,17 @@ class SentNotification < ActiveRecord::Base
reply_key: reply_key
)
- create(params)
+ create(attrs)
end
- def record_note(note, recipient_id, reply_key, params = {})
- params[:line_code] = note.line_code
+ def record_note(note, recipient_id, reply_key, attrs = {})
+ if note.diff_note?
+ attrs[:note_type] = note.type
+
+ attrs.merge!(note.diff_attributes)
+ end
- record(note.noteable, recipient_id, reply_key, params)
+ record(note.noteable, recipient_id, reply_key, attrs)
end
end
@@ -66,12 +72,50 @@ class SentNotification < ActiveRecord::Base
end
end
+ def position=(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
+
+ super(new_position)
+ end
+
def to_param
self.reply_key
end
+ def note_attributes
+ {
+ project: self.project,
+ author: self.recipient,
+ type: self.note_type,
+ noteable_type: self.noteable_type,
+ noteable_id: self.noteable_id,
+ commit_id: self.commit_id,
+ line_code: self.line_code,
+ position: self.position.to_json
+ }
+ end
+
+ def create_note(note)
+ Notes::CreateService.new(
+ self.project,
+ self.recipient,
+ self.note_attributes.merge(note: note)
+ ).execute
+ end
+
private
+ def note_valid
+ Note.new(note_attributes.merge(note: "Test")).valid?
+ end
+
def keep_around_commit
project.repository.keep_around(self.commit_id)
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 5036a3e300c..79c670cb35a 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -15,7 +15,7 @@ class User < ActiveRecord::Base
add_authentication_token_field :authentication_token
default_value_for :admin, false
- default_value_for :external, false
+ default_value_for(:external) { current_application_settings.user_default_external }
default_value_for :can_create_group, gitlab_config.default_can_create_group
default_value_for :can_create_team, false
default_value_for :hide_no_ssh_key, false
@@ -653,7 +653,7 @@ class User < ActiveRecord::Base
end
def avatar_url(size = nil, scale = 2)
- if avatar.present?
+ if self[:avatar].present?
[gitlab_config.url, avatar.url].join
else
GravatarService.new.execute(email, size, scale)
diff --git a/app/services/audit_event_service.rb b/app/services/audit_event_service.rb
index a7f090655e1..8a000585e89 100644
--- a/app/services/audit_event_service.rb
+++ b/app/services/audit_event_service.rb
@@ -7,7 +7,7 @@ class AuditEventService
@details = {
with: @details[:with],
target_id: @author.id,
- target_type: "User",
+ target_type: 'User',
target_details: @author.name,
}
diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb
index e57b95f21ec..e294a962352 100644
--- a/app/services/auth/container_registry_authentication_service.rb
+++ b/app/services/auth/container_registry_authentication_service.rb
@@ -20,9 +20,11 @@ module Auth
token.issuer = registry.issuer
token.audience = AUDIENCE
token.expire_time = token_expire_at
+
token[:access] = names.map do |name|
{ type: 'repository', name: name, actions: %w(*) }
end
+
token.encoded
end
diff --git a/app/services/commits/change_service.rb b/app/services/commits/change_service.rb
index 6b69cb53b2c..c578097376a 100644
--- a/app/services/commits/change_service.rb
+++ b/app/services/commits/change_service.rb
@@ -23,7 +23,7 @@ module Commits
private
def check_push_permissions
- allowed = ::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(@target_branch)
+ allowed = ::Gitlab::GitAccess.new(current_user, project, 'web').can_push_to_branch?(@target_branch)
unless allowed
raise ValidationError.new('You are not allowed to push into this branch')
diff --git a/app/services/compare_service.rb b/app/services/compare_service.rb
index e2bccbdbcc3..149822aa647 100644
--- a/app/services/compare_service.rb
+++ b/app/services/compare_service.rb
@@ -3,7 +3,7 @@ require 'securerandom'
# Compare 2 branches for one repo or between repositories
# and return Gitlab::Git::Compare object that responds to commits and diffs
class CompareService
- def execute(source_project, source_branch, target_project, target_branch, diff_options = {})
+ def execute(source_project, source_branch, target_project, target_branch)
source_commit = source_project.commit(source_branch)
return unless source_commit
diff --git a/app/services/create_branch_service.rb b/app/services/create_branch_service.rb
index cc128563437..d874582d54f 100644
--- a/app/services/create_branch_service.rb
+++ b/app/services/create_branch_service.rb
@@ -3,17 +3,20 @@ require_relative 'base_service'
class CreateBranchService < BaseService
def execute(branch_name, ref, source_project: @project)
valid_branch = Gitlab::GitRefValidator.validate(branch_name)
- if valid_branch == false
+
+ unless valid_branch
return error('Branch name is invalid')
end
repository = project.repository
existing_branch = repository.find_branch(branch_name)
+
if existing_branch
return error('Branch already exists')
end
new_branch = nil
+
if source_project != @project
repository.with_tmp_ref do |tmp_ref|
repository.fetch_ref(
@@ -29,7 +32,6 @@ class CreateBranchService < BaseService
end
if new_branch
- # GitPushService handles execution of services and hooks for branch pushes
success(new_branch)
else
error('Invalid reference name')
@@ -39,8 +41,6 @@ class CreateBranchService < BaseService
end
def success(branch)
- out = super()
- out[:branch] = branch
- out
+ super().merge(branch: branch)
end
end
diff --git a/app/services/create_release_service.rb b/app/services/create_release_service.rb
index f029db72d40..d6d4afcf29a 100644
--- a/app/services/create_release_service.rb
+++ b/app/services/create_release_service.rb
@@ -23,8 +23,6 @@ class CreateReleaseService < BaseService
end
def success(release)
- out = super()
- out[:release] = release
- out
+ super().merge(release: release)
end
end
diff --git a/app/services/create_snippet_service.rb b/app/services/create_snippet_service.rb
index 9884cb96661..95cc9baf406 100644
--- a/app/services/create_snippet_service.rb
+++ b/app/services/create_snippet_service.rb
@@ -1,10 +1,10 @@
class CreateSnippetService < BaseService
def execute
- if project.nil?
- snippet = PersonalSnippet.new(params)
- else
- snippet = project.snippets.build(params)
- end
+ snippet = if project
+ project.snippets.build(params)
+ else
+ PersonalSnippet.new(params)
+ end
unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level])
deny_visibility_level(snippet)
diff --git a/app/services/create_tag_service.rb b/app/services/create_tag_service.rb
index bd8d982e1fb..c0e7ecf6a96 100644
--- a/app/services/create_tag_service.rb
+++ b/app/services/create_tag_service.rb
@@ -9,6 +9,7 @@ class CreateTagService < BaseService
message.strip! if message
new_tag = nil
+
begin
new_tag = repository.add_tag(current_user, tag_name, target, message)
rescue Rugged::TagError
@@ -22,6 +23,7 @@ class CreateTagService < BaseService
CreateReleaseService.new(@project, @current_user).
execute(tag_name, release_description)
end
+
success.merge(tag: new_tag)
else
error("Target #{target} is invalid")
diff --git a/app/services/delete_branch_service.rb b/app/services/delete_branch_service.rb
index 752a7029952..332c55581a1 100644
--- a/app/services/delete_branch_service.rb
+++ b/app/services/delete_branch_service.rb
@@ -5,7 +5,6 @@ class DeleteBranchService < BaseService
repository = project.repository
branch = repository.find_branch(branch_name)
- # No such branch
unless branch
return error('No such branch', 404)
end
@@ -14,18 +13,15 @@ class DeleteBranchService < BaseService
return error('Cannot remove HEAD branch', 405)
end
- # Dont allow remove of protected branch
if project.protected_branch?(branch_name)
return error('Protected branch cant be removed', 405)
end
- # Dont allow user to remove branch if he is not allowed to push
unless current_user.can?(:push_code, project)
return error('You dont have push access to repo', 405)
end
if repository.rm_branch(current_user, branch_name)
- # GitPushService handles execution of services and hooks for branch pushes
success('Branch was removed')
else
error('Failed to remove branch')
@@ -35,15 +31,11 @@ class DeleteBranchService < BaseService
end
def error(message, return_code = 400)
- out = super(message)
- out[:return_code] = return_code
- out
+ super(message).merge(return_code: return_code)
end
def success(message)
- out = super()
- out[:message] = message
- out
+ super().merge(message: message)
end
def build_push_data(branch)
diff --git a/app/services/delete_tag_service.rb b/app/services/delete_tag_service.rb
index de3352a6756..1e41fbe34b6 100644
--- a/app/services/delete_tag_service.rb
+++ b/app/services/delete_tag_service.rb
@@ -5,7 +5,6 @@ class DeleteTagService < BaseService
repository = project.repository
tag = repository.find_tag(tag_name)
- # No such tag
unless tag
return error('No such tag', 404)
end
@@ -26,15 +25,11 @@ class DeleteTagService < BaseService
end
def error(message, return_code = 400)
- out = super(message)
- out[:return_code] = return_code
- out
+ super(message).merge(return_code: return_code)
end
def success(message)
- out = super()
- out[:message] = message
- out
+ super().merge(message: message)
end
def build_push_data(tag)
diff --git a/app/services/files/base_service.rb b/app/services/files/base_service.rb
index 0326a8823e9..37c5e321b39 100644
--- a/app/services/files/base_service.rb
+++ b/app/services/files/base_service.rb
@@ -15,7 +15,6 @@ module Files
params[:file_content]
end
- # Validate parameters
validate
# Create new branch if it different from source_branch
@@ -26,7 +25,7 @@ module Files
if commit
success
else
- error("Something went wrong. Your changes were not committed")
+ error('Something went wrong. Your changes were not committed')
end
rescue Repository::CommitError, Gitlab::Git::Repository::InvalidBlobName, GitHooksService::PreReceiveError, ValidationError => ex
error(ex.message)
@@ -43,7 +42,7 @@ module Files
end
def validate
- allowed = ::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(@target_branch)
+ allowed = ::Gitlab::GitAccess.new(current_user, project, 'web').can_push_to_branch?(@target_branch)
unless allowed
raise_error("You are not allowed to push into this branch")
@@ -51,12 +50,12 @@ module Files
unless project.empty_repo?
unless @source_project.repository.branch_names.include?(@source_branch)
- raise_error("You can only create or edit files when you are on a branch")
+ raise_error('You can only create or edit files when you are on a branch')
end
if different_branch?
if repository.branch_names.include?(@target_branch)
- raise_error("Branch with such name already exists. You need to switch to this branch in order to make changes")
+ raise_error('Branch with such name already exists. You need to switch to this branch in order to make changes')
end
end
end
diff --git a/app/services/files/create_service.rb b/app/services/files/create_service.rb
index e4cde4a2fd8..8eaf6db8012 100644
--- a/app/services/files/create_service.rb
+++ b/app/services/files/create_service.rb
@@ -29,7 +29,7 @@ module Files
blob = repository.blob_at_branch(@source_branch, @file_path)
if blob
- raise_error("Your changes could not be committed because a file with the same name already exists")
+ raise_error('Your changes could not be committed because a file with the same name already exists')
end
end
end
diff --git a/app/services/git_tag_push_service.rb b/app/services/git_tag_push_service.rb
index 299a0a967b0..58573078048 100644
--- a/app/services/git_tag_push_service.rb
+++ b/app/services/git_tag_push_service.rb
@@ -26,6 +26,7 @@ class GitTagPushService < BaseService
unless Gitlab::Git.blank_ref?(params[:newrev])
tag_name = Gitlab::Git.ref_name(params[:ref])
tag = project.repository.find_tag(tag_name)
+
if tag && tag.target == params[:newrev]
commit = project.commit(tag.target)
commits = [commit].compact
diff --git a/app/services/issues/bulk_update_service.rb b/app/services/issues/bulk_update_service.rb
index 15825b81685..cd08c3a0cb9 100644
--- a/app/services/issues/bulk_update_service.rb
+++ b/app/services/issues/bulk_update_service.rb
@@ -9,6 +9,7 @@ module Issues
end
issues = Issue.where(id: issues_ids)
+
issues.each do |issue|
next unless can?(current_user, :update_issue, issue)
diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb
index 3bec66cea88..f1b1d90c457 100644
--- a/app/services/merge_requests/merge_service.rb
+++ b/app/services/merge_requests/merge_service.rb
@@ -34,7 +34,7 @@ module MergeRequests
committer: committer
}
- commit_id = repository.merge(current_user, merge_request.source_sha, merge_request.target_branch, options)
+ commit_id = repository.merge(current_user, merge_request.diff_head_sha, merge_request.target_branch, options)
merge_request.update(merge_commit_sha: commit_id)
rescue GitHooksService::PreReceiveError => e
merge_request.update(merge_error: e.message)
diff --git a/app/services/merge_requests/merge_when_build_succeeds_service.rb b/app/services/merge_requests/merge_when_build_succeeds_service.rb
index 870f5705184..4ad5fb08311 100644
--- a/app/services/merge_requests/merge_when_build_succeeds_service.rb
+++ b/app/services/merge_requests/merge_when_build_succeeds_service.rb
@@ -12,7 +12,7 @@ module MergeRequests
merge_request.merge_when_build_succeeds = true
merge_request.merge_user = @current_user
- SystemNoteService.merge_when_build_succeeds(merge_request, @project, @current_user, merge_request.last_commit)
+ SystemNoteService.merge_when_build_succeeds(merge_request, @project, @current_user, merge_request.diff_head_commit)
end
merge_request.save
diff --git a/app/services/merge_requests/post_merge_service.rb b/app/services/merge_requests/post_merge_service.rb
index 064910f81f7..8437d9b8b43 100644
--- a/app/services/merge_requests/post_merge_service.rb
+++ b/app/services/merge_requests/post_merge_service.rb
@@ -20,6 +20,7 @@ module MergeRequests
return unless merge_request.target_branch == project.default_branch
closed_issues = merge_request.closes_issues(current_user)
+
closed_issues.each do |issue|
if can?(current_user, :update_issue, issue)
Issues::CloseService.new(project, current_user, {}).execute(issue, commit: merge_request)
diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb
index fe0579744b4..b11ecd97a57 100644
--- a/app/services/merge_requests/refresh_service.rb
+++ b/app/services/merge_requests/refresh_service.rb
@@ -34,10 +34,10 @@ module MergeRequests
def close_merge_requests
commit_ids = @commits.map(&:id)
merge_requests = @project.merge_requests.opened.where(target_branch: @branch_name).to_a
- merge_requests = merge_requests.select(&:last_commit)
+ merge_requests = merge_requests.select(&:diff_head_commit)
merge_requests = merge_requests.select do |merge_request|
- commit_ids.include?(merge_request.last_commit.id)
+ commit_ids.include?(merge_request.diff_head_sha)
end
merge_requests.uniq.select(&:source_project).each do |merge_request|
@@ -60,20 +60,15 @@ module MergeRequests
merge_requests.each do |merge_request|
if merge_request.source_branch == @branch_name || force_push?
- merge_request.reload_code
- merge_request.mark_as_unchecked
+ merge_request.reload_diff
else
mr_commit_ids = merge_request.commits.map(&:id)
push_commit_ids = @commits.map(&:id)
matches = mr_commit_ids & push_commit_ids
-
- if matches.any?
- merge_request.reload_code
- merge_request.mark_as_unchecked
- else
- merge_request.mark_as_unchecked
- end
+ merge_request.reload_diff if matches.any?
end
+
+ merge_request.mark_as_unchecked
end
end
@@ -94,12 +89,10 @@ module MergeRequests
merge_request = merge_requests_for_source_branch.first
return unless merge_request
- last_commit = merge_request.last_commit
-
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(last_commit.id, @newrev)
+ common_ref = @project.repository.merge_base(merge_request.diff_head_sha, @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
diff --git a/app/services/merge_requests/reopen_service.rb b/app/services/merge_requests/reopen_service.rb
index 8279ad2001b..eb88ae9d11c 100644
--- a/app/services/merge_requests/reopen_service.rb
+++ b/app/services/merge_requests/reopen_service.rb
@@ -6,7 +6,7 @@ module MergeRequests
create_note(merge_request)
notification_service.reopen_mr(merge_request, current_user)
execute_hooks(merge_request, 'reopen')
- merge_request.reload_code
+ merge_request.reload_diff
merge_request.mark_as_unchecked
end
diff --git a/app/services/notes/diff_position_update_service.rb b/app/services/notes/diff_position_update_service.rb
new file mode 100644
index 00000000000..0cb731f5bc3
--- /dev/null
+++ b/app/services/notes/diff_position_update_service.rb
@@ -0,0 +1,30 @@
+module Notes
+ class DiffPositionUpdateService < BaseService
+ def execute(note)
+ new_position = tracer.trace(note.position)
+
+ # Don't update the position if the type doesn't match, since that means
+ # the diff line commented on was changed, and the comment is now outdated
+ old_position = note.position
+ if new_position &&
+ new_position != old_position &&
+ new_position.type == old_position.type
+
+ note.position = new_position
+ end
+
+ note
+ end
+
+ private
+
+ def tracer
+ @tracer ||= Gitlab::Diff::PositionTracer.new(
+ repository: project.repository,
+ old_diff_refs: params[:old_diff_refs],
+ new_diff_refs: params[:new_diff_refs],
+ paths: params[:paths]
+ )
+ end
+ end
+end
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index 590350a11e5..ab6e51209ee 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -153,6 +153,7 @@ class NotificationService
else
mentioned_users
end
+
recipients = recipients.concat(participants)
# Merge project watchers
@@ -176,6 +177,7 @@ class NotificationService
# build notify method like 'note_commit_email'
notify_method = "note_#{note.noteable_type.underscore}_email".to_sym
+
recipients.each do |recipient|
mailer.send(notify_method, recipient.id, note.id).deliver_later
end
diff --git a/app/services/projects/housekeeping_service.rb b/app/services/projects/housekeeping_service.rb
index a47df22f1ba..c9ad710b7bf 100644
--- a/app/services/projects/housekeeping_service.rb
+++ b/app/services/projects/housekeeping_service.rb
@@ -7,8 +7,6 @@
#
module Projects
class HousekeepingService < BaseService
- include Gitlab::ShellAdapter
-
LEASE_TIMEOUT = 3600
class LeaseTaken < StandardError
@@ -24,10 +22,10 @@ module Projects
def execute
raise LeaseTaken unless try_obtain_lease
- GitlabShellOneShotWorker.perform_async(:gc, @project.repository_storage_path, @project.path_with_namespace)
+ GitGarbageCollectWorker.perform_async(@project.id)
ensure
Gitlab::Metrics.measure(:reset_pushes_since_gc) do
- @project.update_column(:pushes_since_gc, 0)
+ update_pushes_since_gc(0)
end
end
@@ -37,12 +35,18 @@ module Projects
def increment!
Gitlab::Metrics.measure(:increment_pushes_since_gc) do
- @project.increment!(:pushes_since_gc)
+ update_pushes_since_gc(@project.pushes_since_gc + 1)
end
end
private
+ def update_pushes_since_gc(new_value)
+ if Gitlab::ExclusiveLease.new("project_housekeeping:update_pushes_since_gc:#{project.id}", timeout: 60).try_obtain
+ @project.update_column(:pushes_since_gc, new_value)
+ end
+ end
+
def try_obtain_lease
Gitlab::Metrics.measure(:obtain_housekeeping_lease) do
lease = ::Gitlab::ExclusiveLease.new("project_housekeeping:#{@project.id}", timeout: LEASE_TIMEOUT)
diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb
index 3f507d5c400..6afc048576d 100644
--- a/app/services/projects/import_export/export_service.rb
+++ b/app/services/projects/import_export/export_service.rb
@@ -38,6 +38,8 @@ module Projects
end
def cleanup_and_notify
+ Rails.logger.error("Import/Export - Project #{project.name} with ID: #{project.id} export error - #{@shared.errors.join(', ')}")
+
FileUtils.rm_rf(@shared.export_path)
notify_error
@@ -45,6 +47,8 @@ module Projects
end
def notify_success
+ Rails.logger.info("Import/Export - Project #{project.name} with ID: #{project.id} successfully exported")
+
notification_service.project_exported(@project, @current_user)
end
diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb
index 941df08995c..f06311511cc 100644
--- a/app/services/projects/update_service.rb
+++ b/app/services/projects/update_service.rb
@@ -3,10 +3,11 @@ module Projects
def execute
# check that user is allowed to set specified visibility_level
new_visibility = params[:visibility_level]
+
if new_visibility && new_visibility.to_i != project.visibility_level
unless can?(current_user, :change_visibility_level, project) &&
Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility)
-
+
deny_visibility_level(project, new_visibility)
return project
end
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index b868d2e7e83..1ab3b5789bc 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -82,7 +82,7 @@ class SystemNoteService
end
body << ' ' << 'label'.pluralize(labels_count)
- body = "#{body.capitalize}"
+ body = body.capitalize
create_note(noteable: noteable, project: project, author: author, note: body)
end
@@ -125,7 +125,7 @@ class SystemNoteService
# Returns the created Note object
def self.change_status(noteable, project, author, status, source)
body = "Status changed to #{status}"
- body += " by #{source.gfm_reference(project)}" if source
+ body << " by #{source.gfm_reference(project)}" if source
create_note(noteable: noteable, project: project, author: author, note: body)
end
@@ -139,7 +139,7 @@ class SystemNoteService
# Called when 'merge when build succeeds' is canceled
def self.cancel_merge_when_build_succeeds(noteable, project, author)
- body = "Canceled the automatic merge"
+ body = 'Canceled the automatic merge'
create_note(noteable: noteable, project: project, author: author, note: body)
end
@@ -236,6 +236,7 @@ class SystemNoteService
else
'deleted'
end
+
body = "#{verb} #{branch_type.to_s} branch `#{branch}`".capitalize
create_note(noteable: noteable, project: project, author: author, note: body)
end
diff --git a/app/services/update_release_service.rb b/app/services/update_release_service.rb
index 0c0f68d169b..0ee1ff2d7d9 100644
--- a/app/services/update_release_service.rb
+++ b/app/services/update_release_service.rb
@@ -21,8 +21,6 @@ class UpdateReleaseService < BaseService
end
def success(release)
- out = super()
- out[:release] = release
- out
+ super().merge(release: release)
end
end
diff --git a/app/services/update_snippet_service.rb b/app/services/update_snippet_service.rb
index 93af8f21972..a6bb36821c3 100644
--- a/app/services/update_snippet_service.rb
+++ b/app/services/update_snippet_service.rb
@@ -9,6 +9,7 @@ class UpdateSnippetService < BaseService
def execute
# check that user is allowed to set specified visibility_level
new_visibility = params[:visibility_level]
+
if new_visibility && new_visibility.to_i != snippet.visibility_level
unless Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility)
deny_visibility_level(snippet, new_visibility)
diff --git a/app/validators/addressable_url_validator.rb b/app/validators/addressable_url_validator.rb
new file mode 100644
index 00000000000..09bfa613cbe
--- /dev/null
+++ b/app/validators/addressable_url_validator.rb
@@ -0,0 +1,45 @@
+# AddressableUrlValidator
+#
+# Custom validator for URLs. This is a stricter version of UrlValidator - it also checks
+# for using the right protocol, but it actually parses the URL checking for any syntax errors.
+# The regex is also different from `URI` as we use `Addressable::URI` here.
+#
+# By default, only URLs for http, https, ssh, and git protocols will be considered valid.
+# Provide a `:protocols` option to configure accepted protocols.
+#
+# Example:
+#
+# class User < ActiveRecord::Base
+# validates :personal_url, addressable_url: true
+#
+# validates :ftp_url, addressable_url: { protocols: %w(ftp) }
+#
+# validates :git_url, addressable_url: { protocols: %w(http https ssh git) }
+# end
+#
+class AddressableUrlValidator < ActiveModel::EachValidator
+ DEFAULT_OPTIONS = { protocols: %w(http https ssh git) }
+
+ def validate_each(record, attribute, value)
+ unless valid_url?(value)
+ record.errors.add(attribute, "must be a valid URL")
+ end
+ end
+
+ private
+
+ def valid_url?(value)
+ return false unless value
+
+ valid_protocol?(value) && valid_uri?(value)
+ end
+
+ def valid_uri?(value)
+ Gitlab::UrlSanitizer.valid?(value)
+ end
+
+ def valid_protocol?(value)
+ options = DEFAULT_OPTIONS.merge(self.options)
+ value =~ /\A#{URI.regexp(options[:protocols])}\z/
+ end
+end
diff --git a/app/views/admin/abuse_reports/_abuse_report.html.haml b/app/views/admin/abuse_reports/_abuse_report.html.haml
index 862b86d9d4a..dd2e7ebd030 100644
--- a/app/views/admin/abuse_reports/_abuse_report.html.haml
+++ b/app/views/admin/abuse_reports/_abuse_report.html.haml
@@ -3,14 +3,14 @@
%tr
%td
- if user
- = link_to user.name, [:admin, user]
+ = link_to user.name, user
.light.small
Joined #{time_ago_with_tooltip(user.created_at)}
- else
(removed)
%td
- if reporter
- = link_to reporter.name, [:admin, reporter]
+ = link_to reporter.name, reporter
- else
(removed)
.light.small
diff --git a/app/views/admin/appearances/_form.html.haml b/app/views/admin/appearances/_form.html.haml
index dc083e50178..92e2dae4842 100644
--- a/app/views/admin/appearances/_form.html.haml
+++ b/app/views/admin/appearances/_form.html.haml
@@ -13,7 +13,7 @@
.col-sm-10
= f.text_area :description, class: "form-control", rows: 10
.hint
- Description parsed with #{link_to "GitLab Flavored Markdown", help_page_path('markdown', 'markdown'), target: '_blank'}.
+ Description parsed with #{link_to "GitLab Flavored Markdown", help_page_path('markdown/markdown'), target: '_blank'}.
.form-group
= f.label :logo, class: 'control-label'
.col-sm-10
diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
index c1f70bc1866..538d8176ce7 100644
--- a/app/views/admin/application_settings/_form.html.haml
+++ b/app/views/admin/application_settings/_form.html.haml
@@ -38,11 +38,17 @@
= source
%span.help-block#import-sources-help
Enabled sources for code import during project creation. OmniAuth must be configured for GitHub
- = link_to "(?)", help_page_path("integration", "github")
+ = link_to "(?)", help_page_path("integration/github")
, Bitbucket
- = link_to "(?)", help_page_path("integration", "bitbucket")
+ = link_to "(?)", help_page_path("integration/bitbucket")
and GitLab.com
- = link_to "(?)", help_page_path("integration", "gitlab")
+ = link_to "(?)", help_page_path("integration/gitlab")
+ .form-group
+ %label.control-label.col-sm-2 Enabled Git access protocols
+ .col-sm-10
+ = select(:application_setting, :enabled_git_access_protocol, [['Both SSH and HTTP(S)', nil], ['Only SSH', 'ssh'], ['Only HTTP(S)', 'http']], {}, class: 'form-control')
+ %span.help-block#clone-protocol-help
+ Allow only the selected protocols to be used for Git access.
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
@@ -94,6 +100,13 @@
= f.label :user_oauth_applications do
= f.check_box :user_oauth_applications
Allow users to register any application to use GitLab as an OAuth provider
+ .form-group
+ = f.label :user_default_external, 'New users set to external', class: 'control-label col-sm-2'
+ .col-sm-10
+ .checkbox
+ = f.label :user_default_external do
+ = f.check_box :user_default_external
+ Newly registered users will by default be external
%fieldset
%legend Sign-in Restrictions
diff --git a/app/views/admin/deploy_keys/new.html.haml b/app/views/admin/deploy_keys/new.html.haml
index 15aa059c93d..5c410a695bf 100644
--- a/app/views/admin/deploy_keys/new.html.haml
+++ b/app/views/admin/deploy_keys/new.html.haml
@@ -14,7 +14,7 @@
.col-sm-10
%p.light
Paste a machine public key here. Read more about how to generate it
- = link_to "here", help_page_path("ssh", "README")
+ = link_to "here", help_page_path("ssh/README")
= f.text_area :key, class: "form-control thin_area", rows: 5
.form-actions
diff --git a/app/views/admin/groups/_group.html.haml b/app/views/admin/groups/_group.html.haml
index 9025aaac097..59fd6c3fea0 100644
--- a/app/views/admin/groups/_group.html.haml
+++ b/app/views/admin/groups/_group.html.haml
@@ -1,28 +1,20 @@
- css_class = '' unless local_assigns[:css_class]
-- css_class += ' no-description' if group.description.blank?
-%li.group-row{ class: css_class }
- .controls.hidden-xs
- = link_to 'Edit', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: 'btn btn-grouped btn-sm'
- = link_to 'Destroy', [:admin, group], data: {confirm: "REMOVE #{group.name}? Are you sure?"}, method: :delete, class: 'btn btn-grouped btn-sm btn-remove'
+%li.group-row.group-admin{ class: css_class }
+ .group-avatar
+ = image_tag group_icon(group), class: 'avatar hidden-xs'
+ .group-details
+ .title
+ = link_to [:admin, group], class: 'group-name' do
+ = group.name
+ .group-stats
+ %span>= pluralize(number_with_delimiter(group.projects.count), 'project')
+ ,
+ %span= pluralize(number_with_delimiter(group.users.count), 'member')
- .stats
- %span
- = icon('bookmark')
- = number_with_delimiter(group.projects.count)
-
- %span
- = icon('users')
- = number_with_delimiter(group.users.count)
-
- %span.visibility-icon.has-tooltip{data: { container: 'body', placement: 'left' }, title: visibility_icon_description(group)}
- = visibility_level_icon(group.visibility_level, fw: false)
-
- = image_tag group_icon(group), class: 'avatar s40 hidden-xs'
- .title
- = link_to [:admin, group], class: 'group-name' do
- = group.name
-
- - if group.description.present?
- .description
- = markdown(group.description, pipeline: :description)
+ - if group.description.present?
+ .description
+ = markdown(group.description, pipeline: :description)
+ .group-controls.hidden-xs
+ = link_to 'Edit', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: 'btn'
+ = link_to 'Delete', [:admin, group], data: { confirm: "Are you sure you want to remove #{group.name}?" }, method: :delete, class: 'btn btn-remove'
diff --git a/app/views/admin/groups/index.html.haml b/app/views/admin/groups/index.html.haml
index 94aa5f5a942..794f910a61f 100644
--- a/app/views/admin/groups/index.html.haml
+++ b/app/views/admin/groups/index.html.haml
@@ -3,41 +3,32 @@
= render "admin/dashboard/head"
%div{ class: container_class }
- %h3.page-title
- Groups (#{number_with_delimiter(@groups.total_count)})
-
- %p.light
- Group allows you to keep projects organized.
- Use groups for uniting related projects.
-
.top-area
- .nav-search
- = form_tag admin_groups_path, method: :get, class: 'form-inline' do
+ .prepend-top-default.append-bottom-default
+ = form_tag admin_groups_path, method: :get, class: 'js-search-form' do |f|
= hidden_field_tag :sort, @sort
- = text_field_tag :name, params[:name], class: "form-control"
- = button_tag "Search", class: "btn submit btn-primary"
-
- .nav-controls
- .dropdown.inline
- %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
- %span.light
- - if @sort.present?
- = sort_options_hash[@sort]
- - else
- = sort_title_recently_created
- %b.caret
- %ul.dropdown-menu
- %li
- = link_to admin_groups_path(sort: sort_value_recently_created) do
- = sort_title_recently_created
- = link_to admin_groups_path(sort: sort_value_oldest_created) do
- = sort_title_oldest_created
- = link_to admin_groups_path(sort: sort_value_recently_updated) do
- = sort_title_recently_updated
- = link_to admin_groups_path(sort: sort_value_oldest_updated) do
- = sort_title_oldest_updated
- = link_to 'New Group', new_admin_group_path, class: "btn btn-new"
-
+ .search-holder
+ - project_name = params[:name].present? ? params[:name] : nil
+ .search-field-holder
+ = search_field_tag :name, project_name, class: "form-control search-text-input js-search-input", autofocus: true, spellcheck: false, placeholder: 'Search by name'
+ = icon("search", class: "search-icon")
+ .dropdown
+ - toggle_text = @sort.present? ? sort_options_hash[@sort] : sort_title_recently_created
+ = dropdown_toggle(toggle_text, { toggle: 'dropdown' })
+ %ul.dropdown-menu.dropdown-menu-align-right
+ %li.dropdown-header
+ Sort by
+ %li
+ = link_to admin_groups_path(sort: sort_value_recently_created, name: project_name) do
+ = sort_title_recently_created
+ = link_to admin_groups_path(sort: sort_value_oldest_created, name: project_name) do
+ = sort_title_oldest_created
+ = link_to admin_groups_path(sort: sort_value_recently_updated, name: project_name) do
+ = sort_title_recently_updated
+ = link_to admin_groups_path(sort: sort_value_oldest_updated, name: project_name) do
+ = sort_title_oldest_updated
+ = link_to new_admin_group_path, class: "btn btn-new" do
+ New Group
%ul.content-list
= render @groups
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index 522153b37e3..40c8169ad9d 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -79,7 +79,7 @@
.panel-body.form-holder
%p.light
Read more about project permissions
- %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink"
+ %strong= link_to "here", help_page_path("permissions/permissions"), class: "vlink"
= form_tag members_update_admin_group_path(@group), id: "new_project_member", class: "bulk_import", method: :put do
%div
diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml
index 7b388cf7862..c217490963f 100644
--- a/app/views/admin/hooks/index.html.haml
+++ b/app/views/admin/hooks/index.html.haml
@@ -3,7 +3,7 @@
System hooks
%p.light
- #{link_to "System hooks ", help_page_path("system_hooks", "system_hooks"), class: "vlink"} can be
+ #{link_to "System hooks ", help_page_path("system_hooks/system_hooks"), class: "vlink"} can be
used for binding events when GitLab creates a User or Project.
%hr
diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml
index 7d2eb423223..7fbce25b2c4 100644
--- a/app/views/admin/projects/index.html.haml
+++ b/app/views/admin/projects/index.html.haml
@@ -1,97 +1,94 @@
- @no_container = true
- page_title "Projects"
-= render 'shared/show_aside'
+- params[:visibility_level] ||= []
+
= render "admin/dashboard/head"
%div{ class: container_class }
- .row.prepend-top-default
- %aside.col-md-3
- .panel.admin-filter
- = form_tag admin_namespaces_projects_path, method: :get, class: '' do
- .form-group
- = label_tag :name, 'Name:'
- = text_field_tag :name, params[:name], class: "form-control"
+ .top-area
+ .prepend-top-default
+ = form_tag admin_namespaces_projects_path, method: :get do |f|
+ .search-holder
+ .search-field-holder
+ = search_field_tag :name, params[:name], class: "form-control search-text-input js-search-input", id: "dashboard_search", autofocus: true, spellcheck: false, placeholder: 'Search by name'
+
+ - if params[:visibility_level].present?
+ = hidden_field_tag 'visibility_level', params[:visibility_level]
+
+ - if params[:sort].present?
+ = hidden_field_tag 'sort', params[:sort]
+
+ - if params[:personal].present?
+ = hidden_field_tag 'visibility_level', 'true'
+
+ - if params[:archived].present?
+ = hidden_field_tag 'archived', 'true'
+
+ = icon("search", class: "search-icon")
+
+ .dropdown
+ - toggle_text = 'Search for Namespace'
+ - if params[:namespace_id].present?
+ - namespace = Namespace.find(params[:namespace_id])
+ - toggle_text = "#{namespace.kind}: #{namespace.path}"
+ = dropdown_toggle(toggle_text, { toggle: 'dropdown' }, { toggle_class: 'js-namespace-select large' })
+ .dropdown-menu.dropdown-select.dropdown-menu-align-right
+ = dropdown_title('Namespaces')
+ = dropdown_filter("Search for Namespace")
+ = dropdown_content
+ = dropdown_loading
+
+ = button_tag "Search", class: "btn btn-primary btn-search"
+
+ %ul.nav-links
+ - opts = params[:visibility_level].present? ? {} : { page: admin_namespaces_projects_path }
+ = nav_link(opts) do
+ = link_to admin_namespaces_projects_path do
+ All
- .form-group
- = label_tag :namespace_id, "Namespace"
- = namespace_select_tag :namespace_id, selected: params[:namespace_id], class: 'input-large'
+ = nav_link(html_options: { class: params[:visibility_level] == Gitlab::VisibilityLevel::PRIVATE.to_s ? 'active' : '' }) do
+ = link_to admin_namespaces_projects_path(visibility_level: Gitlab::VisibilityLevel::PRIVATE) do
+ Private
+ = nav_link(html_options: { class: params[:visibility_level] == Gitlab::VisibilityLevel::INTERNAL.to_s ? 'active' : '' }) do
+ = link_to admin_namespaces_projects_path(visibility_level: Gitlab::VisibilityLevel::INTERNAL) do
+ Internal
+ = nav_link(html_options: { class: params[:visibility_level] == Gitlab::VisibilityLevel::PUBLIC.to_s ? 'active' : '' }) do
+ = link_to admin_namespaces_projects_path(visibility_level: Gitlab::VisibilityLevel::PUBLIC) do
+ Public
- .form-group
- %strong Activity
- .checkbox
- = label_tag :with_push do
- = check_box_tag :with_push, 1, params[:with_push]
- %span Projects with push events
- .checkbox
- = label_tag :abandoned do
- = check_box_tag :abandoned, 1, params[:abandoned]
- %span No activity over 6 month
- .checkbox
- = label_tag :with_archived do
- = check_box_tag :with_archived, 1, params[:with_archived]
- %span Show archived projects
+ .nav-controls
+ = render 'shared/projects/dropdown'
+ = link_to new_project_path, class: 'btn btn-new' do
+ New Project
- %fieldset
- %strong Visibility level:
- .visibility-levels
- - Project.visibility_levels.each do |label, level|
- .checkbox
- %label
- = check_box_tag 'visibility_levels[]', level, params[:visibility_levels].present? && params[:visibility_levels].include?(level.to_s)
- %span.descr
- = visibility_level_icon(level)
- = label
- %fieldset
- %strong Problems
- .checkbox
- = label_tag :last_repository_check_failed do
- = check_box_tag :last_repository_check_failed, 1, params[:last_repository_check_failed]
- %span Last repository check failed
+ .projects-list-holder
+ - if @projects.any?
+ %ul.projects-list.content-list
+ - @projects.each_with_index do |project|
+ %li.project-row
+ .controls.pull-right
+ - if project.archived
+ %span.label.label-warning archived
+ %span.label.label-gray
+ = repository_size(project)
+ = link_to 'Edit', edit_namespace_project_path(project.namespace, project), id: "edit_#{dom_id(project)}", class: "btn"
+ = link_to 'Delete', [project.namespace.becomes(Namespace), project], data: { confirm: remove_project_message(project) }, method: :delete, class: "btn btn-remove"
+ .title
+ = link_to [:admin, project.namespace.becomes(Namespace), project] do
+ .dash-project-avatar
+ = project_icon(project, alt: '', class: 'avatar project-avatar s40')
+ %span.project-full-name
+ %span.namespace-name
+ - if project.namespace
+ = project.namespace.human_name
+ \/
+ %span.project-name.filter-title
+ = project.name
- = hidden_field_tag :sort, params[:sort]
- = button_tag "Search", class: "btn submit btn-primary"
- = link_to "Reset", admin_namespaces_projects_path, class: "btn btn-cancel"
+ - if project.description.present?
+ .description
+ = markdown(project.description, pipeline: :description)
- %section.col-md-9
- .panel.panel-default
- .panel-heading
- Projects (#{@projects.total_count})
- .controls
- .dropdown.inline
- %button.dropdown-toggle.btn.btn-sm{type: 'button', 'data-toggle' => 'dropdown'}
- %span.light
- - if @sort.present?
- = sort_options_hash[@sort]
- - else
- = sort_title_recently_created
- %b.caret
- %ul.dropdown-menu
- %li
- = link_to admin_namespaces_projects_path(sort: sort_value_recently_created) do
- = sort_title_recently_created
- = link_to admin_namespaces_projects_path(sort: sort_value_oldest_created) do
- = sort_title_oldest_created
- = link_to admin_namespaces_projects_path(sort: sort_value_recently_updated) do
- = sort_title_recently_updated
- = link_to admin_namespaces_projects_path(sort: sort_value_oldest_updated) do
- = sort_title_oldest_updated
- = link_to admin_namespaces_projects_path(sort: sort_value_largest_repo) do
- = sort_title_largest_repo
- = link_to 'New Project', new_project_path, class: "btn btn-sm btn-success"
- %ul.well-list
- - @projects.each do |project|
- %li
- .list-item-name
- %span{ class: visibility_level_color(project.visibility_level) }
- = visibility_level_icon(project.visibility_level)
- = link_to project.name_with_namespace, [:admin, project.namespace.becomes(Namespace), project]
- .pull-right
- - if project.archived
- %span.label.label-warning archived
- %span.label.label-gray
- = repository_size(project)
- = link_to 'Edit', edit_namespace_project_path(project.namespace, project), id: "edit_#{dom_id(project)}", class: "btn btn-sm"
- = link_to 'Destroy', [project.namespace.becomes(Namespace), project], data: { confirm: remove_project_message(project) }, method: :delete, class: "btn btn-sm btn-remove"
- - if @projects.blank?
- .nothing-here-block 0 projects matches
- = paginate @projects, theme: "gitlab"
+ = paginate @projects, theme: 'gitlab'
+ - else
+ .nothing-here-block No projects found
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 82d3169c6f9..b2c607361b3 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -99,7 +99,13 @@
.form-group
= f.label :new_namespace_id, "Namespace", class: 'control-label'
.col-sm-10
- = namespace_select_tag :new_namespace_id, selected: params[:namespace_id], class: 'input-large'
+ .dropdown
+ = dropdown_toggle('Search for Namespace', { toggle: 'dropdown', field_name: 'new_namespace_id', show_any: 'false' }, { toggle_class: 'js-namespace-select large' })
+ .dropdown-menu.dropdown-select
+ = dropdown_title('Namespaces')
+ = dropdown_filter("Search for Namespace")
+ = dropdown_content
+ = dropdown_loading
.form-group
.col-sm-offset-2.col-sm-10
@@ -126,7 +132,7 @@
- else
passed.
- = link_to icon('question-circle'), help_page_path('administration', 'repository_checks')
+ = link_to icon('question-circle'), help_page_path('administration/repository_checks')
.form-group
= f.submit 'Trigger repository check', class: 'btn btn-primary'
diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml
index fe0b9d3a491..3145212728f 100644
--- a/app/views/admin/users/_form.html.haml
+++ b/app/views/admin/users/_form.html.haml
@@ -44,7 +44,7 @@
%legend Access
.form-group
= f.label :projects_limit, class: 'control-label'
- .col-sm-10= f.number_field :projects_limit, class: 'form-control'
+ .col-sm-10= f.number_field :projects_limit, min: 0, class: 'form-control'
.form-group
= f.label :can_create_group, class: 'control-label'
diff --git a/app/views/admin/users/_user.html.haml b/app/views/admin/users/_user.html.haml
new file mode 100644
index 00000000000..d3519f616f6
--- /dev/null
+++ b/app/views/admin/users/_user.html.haml
@@ -0,0 +1,42 @@
+%li.user-row
+ .user-avatar
+ = image_tag avatar_icon(user), class: "avatar", alt: ''
+ .user-details
+ .user-name
+ = link_to user.name, [:admin, user]
+ - if user.blocked?
+ %span.label.label-danger blocked
+ - if user.admin?
+ %span.label.label-success Admin
+ - if user.external?
+ %span.label.label-default External
+ - if user == current_user
+ %span It's you!
+ .user-email
+ = mail_to user.email, user.email
+ .controls.pull-right
+ = link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: 'btn'
+ - unless user == current_user
+ .dropdown.inline
+ %a.dropdown-new.btn.btn-default#project-settings-button{href: '#', data: { toggle: 'dropdown' } }
+ = icon('cog')
+ = icon('caret-down')
+ %ul.dropdown-menu.dropdown-menu-align-right
+ %li.dropdown-header
+ Settings
+ %li
+ - if user.ldap_blocked?
+ %span.small Cannot unblock LDAP blocked users
+ - elsif user.blocked?
+ = link_to 'Unblock', unblock_admin_user_path(user), method: :put
+ - else
+ = link_to 'Block', block_admin_user_path(user), data: { confirm: 'USER WILL BE BLOCKED! Are you sure?' }, method: :put
+ - if user.access_locked?
+ %li
+ = link_to 'Unlock', unlock_admin_user_path(user), method: :put, class: 'btn-grouped btn btn-xs btn-success', data: { confirm: 'Are you sure?' }
+ - if user.can_be_removed?
+ %li.divider
+ %li
+ = link_to 'Delete User', [:admin, user], data: { confirm: "USER #{user.name} WILL BE REMOVED! All issues, merge requests and groups linked to this user will also be removed! Consider cancelling this deletion and blocking the user instead. Are you sure?" },
+ class: 'btn btn-remove btn-block',
+ method: :delete
diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml
index 21bb99a792c..357123c2c13 100644
--- a/app/views/admin/users/index.html.haml
+++ b/app/views/admin/users/index.html.haml
@@ -1,110 +1,78 @@
- @no_container = true
- page_title "Users"
-= render 'shared/show_aside'
= render "admin/dashboard/head"
%div{ class: container_class }
- .admin-filter
- %ul.nav-links
- %li{class: "#{'active' unless params[:filter]}"}
- = link_to admin_users_path do
- Active
- %small.badge= number_with_delimiter(User.active.count)
- %li{class: "#{'active' if params[:filter] == "admins"}"}
- = link_to admin_users_path(filter: "admins") do
- Admins
- %small.badge= number_with_delimiter(User.admins.count)
- %li.filter-two-factor-enabled{class: "#{'active' if params[:filter] == 'two_factor_enabled'}"}
- = link_to admin_users_path(filter: 'two_factor_enabled') do
- 2FA Enabled
- %small.badge= number_with_delimiter(User.with_two_factor.count)
- %li.filter-two-factor-disabled{class: "#{'active' if params[:filter] == 'two_factor_disabled'}"}
- = link_to admin_users_path(filter: 'two_factor_disabled') do
- 2FA Disabled
- %small.badge= number_with_delimiter(User.without_two_factor.count)
- %li.filter-external{class: "#{'active' if params[:filter] == 'external'}"}
- = link_to admin_users_path(filter: 'external') do
- External
- %small.badge= number_with_delimiter(User.external.count)
- %li{class: "#{'active' if params[:filter] == "blocked"}"}
- = link_to admin_users_path(filter: "blocked") do
- Blocked
- %small.badge= number_with_delimiter(User.blocked.count)
- %li{class: "#{'active' if params[:filter] == "wop"}"}
- = link_to admin_users_path(filter: "wop") do
- Without projects
- %small.badge= number_with_delimiter(User.without_projects.count)
+ .top-area
+ .prepend-top-default
+ = form_tag admin_users_path, method: :get do
+ - if params[:filter].present?
+ = hidden_field_tag "filter", h(params[:filter])
+ .search-holder
+ .search-field-holder
+ = search_field_tag :name, params[:name], placeholder: 'Search by name, email or username', class: 'form-control search-text-input js-search-input', spellcheck: false
+ = icon("search", class: "search-icon")
+ .dropdown
+ - toggle_text = if @sort.present? then sort_options_hash[@sort] else sort_title_name end
+ = dropdown_toggle(toggle_text, { toggle: 'dropdown' })
+ %ul.dropdown-menu.dropdown-menu-align-right
+ %li.dropdown-header
+ Sort by
+ %li
+ = link_to admin_users_path(sort: sort_value_name, filter: params[:filter]) do
+ = sort_title_name
+ = link_to admin_users_path(sort: sort_value_recently_signin, filter: params[:filter]) do
+ = sort_title_recently_signin
+ = link_to admin_users_path(sort: sort_value_oldest_signin, filter: params[:filter]) do
+ = sort_title_oldest_signin
+ = link_to admin_users_path(sort: sort_value_recently_created, filter: params[:filter]) do
+ = sort_title_recently_created
+ = link_to admin_users_path(sort: sort_value_oldest_created, filter: params[:filter]) do
+ = sort_title_oldest_created
+ = link_to admin_users_path(sort: sort_value_recently_updated, filter: params[:filter]) do
+ = sort_title_recently_updated
+ = link_to admin_users_path(sort: sort_value_oldest_updated, filter: params[:filter]) do
+ = sort_title_oldest_updated
+ = link_to 'New User', new_admin_user_path, class: 'btn btn-new btn-search'
- .row-content-block.second-block
- .pull-right
- .dropdown.inline
- %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
- %span.light
- - if @sort.present?
- = sort_options_hash[@sort]
- - else
- = sort_title_name
- %b.caret
- %ul.dropdown-menu
- %li
- = link_to admin_users_path(sort: sort_value_name, filter: params[:filter]) do
- = sort_title_name
- = link_to admin_users_path(sort: sort_value_recently_signin, filter: params[:filter]) do
- = sort_title_recently_signin
- = link_to admin_users_path(sort: sort_value_oldest_signin, filter: params[:filter]) do
- = sort_title_oldest_signin
- = link_to admin_users_path(sort: sort_value_recently_created, filter: params[:filter]) do
- = sort_title_recently_created
- = link_to admin_users_path(sort: sort_value_oldest_created, filter: params[:filter]) do
- = sort_title_oldest_created
- = link_to admin_users_path(sort: sort_value_recently_updated, filter: params[:filter]) do
- = sort_title_recently_updated
- = link_to admin_users_path(sort: sort_value_oldest_updated, filter: params[:filter]) do
- = sort_title_oldest_updated
+ .nav-block
+ %ul.nav-links.wide.scrolling-tabs.white.scrolling-tabs
+ .fade-left
+ = nav_link(html_options: { class: ('active' unless params[:filter]) }) do
+ = link_to admin_users_path do
+ Active
+ %small.badge= number_with_delimiter(User.active.count)
+ = nav_link(html_options: { class: ('active' if params[:filter] == 'admins') }) do
+ = link_to admin_users_path(filter: "admins") do
+ Admins
+ %small.badge= number_with_delimiter(User.admins.count)
+ = nav_link(html_options: { class: "#{'active' if params[:filter] == 'two_factor_enabled'} filter-two-factor-enabled" }) do
+ = link_to admin_users_path(filter: 'two_factor_enabled') do
+ 2FA Enabled
+ %small.badge= number_with_delimiter(User.with_two_factor.count)
+ = nav_link(html_options: { class: "#{'active' if params[:filter] == 'two_factor_disabled'} filter-two-factor-disabled" }) do
+ = link_to admin_users_path(filter: 'two_factor_disabled') do
+ 2FA Disabled
+ %small.badge= number_with_delimiter(User.without_two_factor.count)
+ = nav_link(html_options: { class: ('active' if params[:filter] == 'external') }) do
+ = link_to admin_users_path(filter: 'external') do
+ External
+ %small.badge= number_with_delimiter(User.external.count)
+ = nav_link(html_options: { class: ('active' if params[:filter] == 'blocked') }) do
+ = link_to admin_users_path(filter: "blocked") do
+ Blocked
+ %small.badge= number_with_delimiter(User.blocked.count)
+ = nav_link(html_options: { class: ('active' if params[:filter] == 'wop') }) do
+ = link_to admin_users_path(filter: "wop") do
+ Without projects
+ %small.badge= number_with_delimiter(User.without_projects.count)
+ .fade-right
- = link_to 'New User', new_admin_user_path, class: "btn btn-new"
- = form_tag admin_users_path, method: :get, class: 'form-inline' do
- .form-group
- = search_field_tag :name, params[:name], placeholder: 'Name, email or username', class: 'form-control', spellcheck: false
- = hidden_field_tag "filter", params[:filter]
- = button_tag class: 'btn btn-primary' do
- %i.fa.fa-search
+ %ul.users-list.content-list
+ - if @users.empty?
+ %li
+ .nothing-here-block No users found.
+ - else
+ = render partial: 'admin/users/user', collection: @users
-
- .panel.panel-default
- %ul.well-list
- - @users.each do |user|
- %li
- .list-item-name
- - if user.blocked?
- = icon("lock", class: "cred")
- - else
- = icon("user", class: "cgreen")
- = link_to user.name, [:admin, user]
- - if user.admin?
- %strong.cred (Admin)
- - if user.external?
- %strong.cred (External)
- - if user == current_user
- %span.cred It's you!
- .pull-right
- %span.light
- %i.fa.fa-envelope
- = mail_to user.email, user.email, class: 'light'
- &nbsp;
- .pull-right
- = link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: 'btn-grouped btn btn-xs'
- - unless user == current_user
- - if user.ldap_blocked?
- = link_to '#', title: 'Cannot unblock LDAP blocked users', data: {toggle: 'tooltip'}, class: 'btn-grouped btn btn-xs btn-success disabled' do
- %i.fa.fa-lock
- Unblock
- - elsif user.blocked?
- = link_to 'Unblock', unblock_admin_user_path(user), method: :put, class: 'btn-grouped btn btn-xs btn-success'
- - else
- = link_to 'Block', block_admin_user_path(user), data: {confirm: 'USER WILL BE BLOCKED! Are you sure?'}, method: :put, class: 'btn-grouped btn btn-xs btn-warning'
- - if user.access_locked?
- = link_to 'Unlock', unlock_admin_user_path(user), method: :put, class: 'btn-grouped btn btn-xs btn-success', data: { confirm: 'Are you sure?' }
- - if user.can_be_removed?
- = link_to 'Destroy', [:admin, user], data: { confirm: "USER #{user.name} WILL BE REMOVED! All issues, merge requests and groups linked to this user will also be removed! Maybe block the user instead? Are you sure?" }, method: :delete, class: 'btn-grouped btn btn-xs btn-remove'
= paginate @users, theme: "gitlab"
diff --git a/app/views/errors/access_denied.html.haml b/app/views/errors/access_denied.html.haml
index 012e9857642..2febeef99d3 100644
--- a/app/views/errors/access_denied.html.haml
+++ b/app/views/errors/access_denied.html.haml
@@ -3,4 +3,4 @@
%h3 Access Denied
%hr
%p You are not allowed to access this page.
-%p Read more about project permissions #{link_to "here", help_page_path("permissions", "permissions"), class: "vlink"}
+%p Read more about project permissions #{link_to "here", help_page_path("permissions/permissions"), class: "vlink"}
diff --git a/app/views/explore/snippets/index.html.haml b/app/views/explore/snippets/index.html.haml
index 9b838b9f3b7..6306fe6d0bf 100644
--- a/app/views/explore/snippets/index.html.haml
+++ b/app/views/explore/snippets/index.html.haml
@@ -10,7 +10,6 @@
- if current_user
.pull-right
= link_to new_snippet_path, class: "btn btn-new", title: "New Snippet" do
- = icon('plus')
New Snippet
.oneline
diff --git a/app/views/groups/group_members/_new_group_member.html.haml b/app/views/groups/group_members/_new_group_member.html.haml
index e7ab4f2409b..13ded2bc455 100644
--- a/app/views/groups/group_members/_new_group_member.html.haml
+++ b/app/views/groups/group_members/_new_group_member.html.haml
@@ -12,7 +12,7 @@
= select_tag :access_level, options_for_select(GroupMember.access_level_roles, @group_member.access_level), class: "project-access-select select2"
.help-block
Read more about role permissions
- %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink"
+ %strong= link_to "here", help_page_path("permissions/permissions"), class: "vlink"
.form-actions
= f.submit 'Add users to group', class: "btn btn-create"
diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml
index 121a7de3ad7..a8fdbd8c426 100644
--- a/app/views/groups/milestones/index.html.haml
+++ b/app/views/groups/milestones/index.html.haml
@@ -6,7 +6,6 @@
.nav-controls
- if can?(current_user, :admin_milestones, @group)
= link_to new_group_milestone_path(@group), class: "btn btn-new" do
- = icon('plus')
New Milestone
.row-content-block
diff --git a/app/views/groups/projects.html.haml b/app/views/groups/projects.html.haml
index c2f2d9912f7..33fee334d93 100644
--- a/app/views/groups/projects.html.haml
+++ b/app/views/groups/projects.html.haml
@@ -7,7 +7,6 @@
- if can? current_user, :admin_group, @group
.controls
= link_to new_project_path(namespace_id: @group.id), class: "btn btn-sm btn-success" do
- = icon('plus')
New Project
%ul.well-list
- @projects.each do |project|
diff --git a/app/views/help/show.html.haml b/app/views/help/show.html.haml
index 0398afb4c1d..be257b51b9e 100644
--- a/app/views/help/show.html.haml
+++ b/app/views/help/show.html.haml
@@ -1,3 +1,3 @@
-- page_title @file.humanize, *@category.split("/").reverse.map(&:humanize)
+- page_title @path.split("/").reverse.map(&:humanize)
.documentation.wiki
= markdown @markdown.gsub('$your_email', current_user.try(:email) || "email@example.com")
diff --git a/app/views/help/ui.html.haml b/app/views/help/ui.html.haml
index d676bc28c89..431d312b4ca 100644
--- a/app/views/help/ui.html.haml
+++ b/app/views/help/ui.html.haml
@@ -549,4 +549,4 @@
%li wiki page
%li help page
- You can check how markdown rendered at #{link_to 'Markdown help page', help_page_path("markdown", "markdown")}.
+ You can check how markdown rendered at #{link_to 'Markdown help page', help_page_path("markdown/markdown")}.
diff --git a/app/views/import/github/new.html.haml b/app/views/import/github/new.html.haml
index 435ed7bd4cb..4c6af0b7908 100644
--- a/app/views/import/github/new.html.haml
+++ b/app/views/import/github/new.html.haml
@@ -38,6 +38,6 @@
As an administrator you may like to configure
- else
Consider asking your GitLab administrator to configure
- = link_to 'GitHub integration', help_page_path("integration", "github")
+ = link_to 'GitHub integration', help_page_path("integration/github")
which will allow login via GitHub and allow importing projects without
generating a Personal Access Token.
diff --git a/app/views/layouts/_flash.html.haml b/app/views/layouts/_flash.html.haml
index cc8ea066cb9..3612f1ce5c6 100644
--- a/app/views/layouts/_flash.html.haml
+++ b/app/views/layouts/_flash.html.haml
@@ -1,4 +1,4 @@
-.flash-container
+.flash-container.flash-container-page
- if alert
.flash-alert
= alert
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index 2234bf79c87..8596bbfdef6 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -8,11 +8,6 @@
- else
= render 'layouts/nav/explore'
- - if current_user
- = link_to current_user, class: 'sidebar-user', title: "Profile", data: {user: current_user.username} do
- = image_tag avatar_icon(current_user, 60), alt: 'Profile', class: 'avatar avatar s36'
- .username
- = current_user.username
= link_to '#', class: "nav-header-btn text-center pin-nav-btn has-tooltip #{'is-active' if pinned_nav?} js-nav-pin", title: pinned_nav? ? "Unpin navigation" : "Pin Navigation", data: {placement: 'right', container: 'body'} do
%span.sr-only Toggle navigation pinning
= icon('thumb-tack')
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index d59a93a8fd7..11cee421a99 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -45,7 +45,9 @@
.dropdown-menu-nav.dropdown-menu-align-right
%ul
%li
- = link_to "Profile", current_user
+ = link_to "Profile", current_user, class: 'profile-link', data: { user: current_user.username }
+ %li
+ = link_to "Profile Settings", profile_path
%li.divider
%li
= link_to "Sign out", destroy_user_session_path, method: :delete, class: "sign-out-link", title: 'Sign out'
diff --git a/app/views/notify/note_merge_request_email.html.haml b/app/views/notify/note_merge_request_email.html.haml
index a3643a00cfe..35c4b862bb7 100644
--- a/app/views/notify/note_merge_request_email.html.haml
+++ b/app/views/notify/note_merge_request_email.html.haml
@@ -1,7 +1,7 @@
-- if @note.legacy_diff_note?
+- if @note.diff_note?
%p.details
New comment on diff for
- = link_to @note.diff_file_path, @target_url
+ = link_to @note.diff_file.file_path, @target_url
\:
= render 'note_message'
diff --git a/app/views/notify/repository_push_email.html.haml b/app/views/notify/repository_push_email.html.haml
index f1532371b2e..c161ecc3463 100644
--- a/app/views/notify/repository_push_email.html.haml
+++ b/app/views/notify/repository_push_email.html.haml
@@ -72,12 +72,11 @@
The diff for this file was not included because it is too large.
- else
%hr
- - diff_commit = diff_file.deleted_file ? @message.diff_refs.first : @message.diff_refs.last
- - blob = @message.project.repository.blob_for_diff(diff_commit, diff_file)
+ - blob = diff_file.blob
- if blob && blob.respond_to?(:text?) && blob_text_viewable?(blob)
%table.code.white
- diff_file.highlighted_diff_lines.each do |line|
- = render "projects/diffs/line", {line: line, diff_file: diff_file, line_code: nil, plain: true}
+ = render "projects/diffs/line", line: line, diff_file: diff_file, plain: true
- else
No preview for this file type
%br
diff --git a/app/views/profiles/_head.html.haml b/app/views/profiles/_head.html.haml
new file mode 100644
index 00000000000..003884a5bd9
--- /dev/null
+++ b/app/views/profiles/_head.html.haml
@@ -0,0 +1,3 @@
+- content_for :page_specific_javascripts do
+ = page_specific_javascript_tag('lib/cropper.js')
+ = page_specific_javascript_tag('profile/application.js')
diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml
index 8efe486e01b..57d16d29158 100644
--- a/app/views/profiles/accounts/show.html.haml
+++ b/app/views/profiles/accounts/show.html.haml
@@ -1,4 +1,5 @@
- page_title "Account"
+= render 'profiles/head'
- if current_user.ldap_user?
.alert.alert-info
diff --git a/app/views/profiles/audit_log.html.haml b/app/views/profiles/audit_log.html.haml
index 9c404b6935f..9fe86e6b291 100644
--- a/app/views/profiles/audit_log.html.haml
+++ b/app/views/profiles/audit_log.html.haml
@@ -1,4 +1,5 @@
- page_title "Audit Log"
+= render 'profiles/head'
.row.prepend-top-default
.col-lg-3.profile-settings-sidebar
diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml
index 6f7fefdb46d..dc499be885b 100644
--- a/app/views/profiles/emails/index.html.haml
+++ b/app/views/profiles/emails/index.html.haml
@@ -1,4 +1,5 @@
- page_title "Emails"
+= render 'profiles/head'
.row.prepend-top-default
.col-lg-3.profile-settings-sidebar
diff --git a/app/views/profiles/keys/_form.html.haml b/app/views/profiles/keys/_form.html.haml
index b3ed59a1a4a..6ea358d9f63 100644
--- a/app/views/profiles/keys/_form.html.haml
+++ b/app/views/profiles/keys/_form.html.haml
@@ -4,7 +4,7 @@
.form-group
= f.label :key, class: 'label-light'
- = f.text_area :key, class: "form-control", rows: 8, required: true
+ = f.text_area :key, class: "form-control", rows: 8, required: true, placeholder: "Don't paste the private part of the SSH key. Paste the public part, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'."
.form-group
= f.label :title, class: 'label-light'
= f.text_field :title, class: "form-control", required: true
diff --git a/app/views/profiles/keys/index.html.haml b/app/views/profiles/keys/index.html.haml
index 6a067a03535..a42b3b8eb38 100644
--- a/app/views/profiles/keys/index.html.haml
+++ b/app/views/profiles/keys/index.html.haml
@@ -11,7 +11,7 @@
Add an SSH key
%p.profile-settings-content
Before you can add an SSH key you need to
- = link_to "generate it.", help_page_path("ssh", "README")
+ = link_to "generate it.", help_page_path("ssh/README")
= render 'form'
%hr
%h5
diff --git a/app/views/profiles/keys/show.html.haml b/app/views/profiles/keys/show.html.haml
index 89f6f01581a..6283ceebf10 100644
--- a/app/views/profiles/keys/show.html.haml
+++ b/app/views/profiles/keys/show.html.haml
@@ -1,2 +1,3 @@
- page_title @key.title, "SSH Keys"
+= render 'profiles/head'
= render "key_details"
diff --git a/app/views/profiles/notifications/show.html.haml b/app/views/profiles/notifications/show.html.haml
index f77738f97f5..844fce59704 100644
--- a/app/views/profiles/notifications/show.html.haml
+++ b/app/views/profiles/notifications/show.html.haml
@@ -1,4 +1,5 @@
- page_title "Notifications"
+= render 'profiles/head'
%div
- if @user.errors.any?
diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml
index 1b45548bd02..71ac367830d 100644
--- a/app/views/profiles/personal_access_tokens/index.html.haml
+++ b/app/views/profiles/personal_access_tokens/index.html.haml
@@ -1,4 +1,5 @@
- page_title "Personal Access Tokens"
+= render 'profiles/head'
.row.prepend-top-default
.col-lg-3.profile-settings-sidebar
diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml
index 1b1b16d656f..2afa026847a 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -1,4 +1,5 @@
- page_title 'Preferences'
+= render 'profiles/head'
= form_for @user, url: profile_preferences_path, remote: true, method: :put, html: {class: 'row prepend-top-default js-preferences-form'} do |f|
.col-lg-3.profile-settings-sidebar
@@ -42,12 +43,12 @@
.form-group
= f.label :dashboard, class: 'label-light' do
Default Dashboard
- = link_to('(?)', help_page_path('profile', 'preferences') + '#default-dashboard', target: '_blank')
+ = link_to('(?)', help_page_path('profile/preferences') + '#default-dashboard', target: '_blank')
= f.select :dashboard, dashboard_choices, {}, class: 'form-control'
.form-group
= f.label :project_view, class: 'label-light' do
Project view
- = link_to('(?)', help_page_path('profile', 'preferences') + '#default-project-view', target: '_blank')
+ = link_to('(?)', help_page_path('profile/preferences') + '#default-project-view', target: '_blank')
= f.select :project_view, project_view_choices, {}, class: 'form-control'
.help-block
Choose what content you want to see on a project's home page.
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index eef50d887c7..d9fa74fad90 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -1,3 +1,5 @@
+= render 'profiles/head'
+
= form_for @user, url: profile_path, method: :put, html: { multipart: true, class: "edit-user prepend-top-default" }, authenticity_token: true do |f|
= form_errors(@user)
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index 593be2617c1..8780da1dec4 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -1,5 +1,6 @@
- page_title 'Two-Factor Authentication', 'Account'
- header_title "Two-Factor Authentication", profile_two_factor_auth_path
+= render 'profiles/head'
.row.prepend-top-default
.col-lg-3
@@ -13,7 +14,7 @@
- else
%p
Download the Google Authenticator application from App Store or Google Play Store and scan this code.
- More information is available in the #{link_to('documentation', help_page_path('profile', 'two_factor_authentication'))}.
+ More information is available in the #{link_to('documentation', help_page_path('profile/two_factor_authentication'))}.
.row.append-bottom-10
.col-md-3
= raw @qr_code
diff --git a/app/views/projects/_bitbucket_import_modal.html.haml b/app/views/projects/_bitbucket_import_modal.html.haml
index 2987f6b5b22..e74fd5b93ea 100644
--- a/app/views/projects/_bitbucket_import_modal.html.haml
+++ b/app/views/projects/_bitbucket_import_modal.html.haml
@@ -10,4 +10,4 @@
as administrator you need to configure
- else
ask your GitLab administrator to configure
- == #{link_to 'OAuth integration', help_page_path("integration", "bitbucket")}.
+ == #{link_to 'OAuth integration', help_page_path("integration/bitbucket")}.
diff --git a/app/views/projects/_builds_settings.html.haml b/app/views/projects/_builds_settings.html.haml
index 0568c2d305e..fff30f11d82 100644
--- a/app/views/projects/_builds_settings.html.haml
+++ b/app/views/projects/_builds_settings.html.haml
@@ -4,7 +4,7 @@
- unless @repository.gitlab_ci_yml
.form-group
%p Builds need to be configured before you can begin using Continuous Integration.
- = link_to 'Get started with Builds', help_page_path('ci/quick_start', 'README'), class: 'btn btn-info'
+ = link_to 'Get started with Builds', help_page_path('ci/quick_start/README'), class: 'btn btn-info'
.form-group
%p Get recent application code using the following command:
.radio
diff --git a/app/views/projects/_gitlab_import_modal.html.haml b/app/views/projects/_gitlab_import_modal.html.haml
index 377cf0187b8..e9f39b16aa7 100644
--- a/app/views/projects/_gitlab_import_modal.html.haml
+++ b/app/views/projects/_gitlab_import_modal.html.haml
@@ -10,4 +10,4 @@
as administrator you need to configure
- else
ask your GitLab administrator to configure
- == #{link_to 'OAuth integration', help_page_path("integration", "gitlab")}.
+ == #{link_to 'OAuth integration', help_page_path("integration/gitlab")}.
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index 540efa4780f..cf11723dc8e 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -1,41 +1,29 @@
- empty_repo = @project.empty_repo?
-.project-home-panel.cover-block.clearfix{:class => ("empty-project" if empty_repo)}
+.project-home-panel.text-center{ class: ("empty-project" if empty_repo) }
%div{ class: container_class }
- .row
- .project-image-container
- = project_icon(@project, alt: '', class: 'project-avatar avatar s70')
- .project-info
- .cover-title.project-home-desc
- %h1
- = @project.name
- %span.visibility-icon.has-tooltip{data: { container: 'body' }, title: visibility_icon_description(@project)}
- = visibility_level_icon(@project.visibility_level, fw: false)
+ = project_icon(@project, alt: @project.name, class: 'project-avatar avatar s70')
+ %h1.project-title
+ = @project.name
+ %span.visibility-icon.has-tooltip{data: { container: 'body' }, title: visibility_icon_description(@project)}
+ = visibility_level_icon(@project.visibility_level, fw: false)
- - if @project.description.present?
- .cover-desc.project-home-desc
- = markdown(@project.description, pipeline: :description)
+ .project-home-desc
+ - if @project.description.present?
+ = markdown(@project.description, pipeline: :description)
- - if forked_from_project = @project.forked_from_project
- .cover-desc
- Forked from
- = link_to project_path(forked_from_project) do
- = forked_from_project.namespace.try(:name)
+ - if forked_from_project = @project.forked_from_project
+ %p
+ Forked from
+ = link_to project_path(forked_from_project) do
+ = forked_from_project.namespace.try(:name)
- .project-repo-buttons.project-action-buttons
- .count-buttons
- = render 'projects/buttons/star'
- = render 'projects/buttons/fork'
+ .project-repo-buttons.project-action-buttons
+ .count-buttons
+ = render 'projects/buttons/star'
+ = render 'projects/buttons/fork'
- .project-clone-holder
- = render "shared/clone_panel"
-
- .project-repo-buttons.btn-group.project-right-buttons
- - if current_user
- .pull-left.append-right-10= render 'shared/members/access_request_buttons', source: @project
-
- = render "projects/buttons/download"
- = render 'projects/buttons/dropdown'
- = render 'shared/notifications/button', notification_setting: @notification_setting
+ .project-clone-holder
+ = render "shared/clone_panel"
:javascript
new Star();
diff --git a/app/views/projects/_last_commit.html.haml b/app/views/projects/_last_commit.html.haml
index 66c30283c7a..630ae7d6140 100644
--- a/app/views/projects/_last_commit.html.haml
+++ b/app/views/projects/_last_commit.html.haml
@@ -1,11 +1,10 @@
-.project-last-commit
- - if commit.status
- = link_to builds_namespace_project_commit_path(commit.project.namespace, commit.project, commit), class: "ci-status ci-#{commit.status}" do
- = ci_icon_for_status(commit.status)
- = ci_label_for_status(commit.status)
+- if commit.status
+ = link_to builds_namespace_project_commit_path(commit.project.namespace, commit.project, commit), class: "ci-status ci-#{commit.status}" do
+ = ci_icon_for_status(commit.status)
+ = ci_label_for_status(commit.status)
- = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id"
- = link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit), class: "commit-row-message"
- &middot;
- #{time_ago_with_tooltip(commit.committed_date, skip_js: true)} by
- = commit_author_link(commit, avatar: true, size: 24)
+= link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id"
+= link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit), class: "commit-row-message"
+&middot;
+#{time_ago_with_tooltip(commit.committed_date, skip_js: true)} by
+= commit_author_link(commit, avatar: true, size: 24)
diff --git a/app/views/projects/_last_push.html.haml b/app/views/projects/_last_push.html.haml
index 434d8644b83..3c6b931f41a 100644
--- a/app/views/projects/_last_push.html.haml
+++ b/app/views/projects/_last_push.html.haml
@@ -7,7 +7,9 @@
%span You pushed to
= link_to namespace_project_commits_path(event.project.namespace, event.project, event.ref_name) do
%strong= event.ref_name
- branch
+ - if @project && event.project != @project
+ %span at
+ %strong= link_to_project event.project
#{time_ago_with_tooltip(event.created_at)}
.pull-right
diff --git a/app/views/projects/_merge_request_settings.html.haml b/app/views/projects/_merge_request_settings.html.haml
index 771a2e0df7d..19b4249374b 100644
--- a/app/views/projects/_merge_request_settings.html.haml
+++ b/app/views/projects/_merge_request_settings.html.haml
@@ -8,4 +8,4 @@
%strong Only allow merge requests to be merged if the build succeeds
.help-block
Builds need to be configured to enable this feature.
- = link_to icon('question-circle'), help_page_path('workflow', 'merge_requests', anchor: 'only-allow-merge-requests-to-be-merged-if-the-build-succeeds')
+ = link_to icon('question-circle'), help_page_path('workflow/merge_requests', anchor: 'only-allow-merge-requests-to-be-merged-if-the-build-succeeds')
diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml
index e4f04ca7764..b1c9895f43e 100644
--- a/app/views/projects/blob/edit.html.haml
+++ b/app/views/projects/blob/edit.html.haml
@@ -4,12 +4,10 @@
%ul.nav-links.no-bottom.js-edit-mode
%li.active
= link_to '#editor' do
- = icon('edit')
Edit File
%li
= link_to '#preview', 'data-preview-url' => namespace_project_preview_blob_path(@project.namespace, @project, @id) do
- = icon('eye')
= editing_preview_title(@blob.name)
= form_tag(namespace_project_update_blob_path(@project.namespace, @project, @id), method: :put, class: 'form-horizontal js-quick-submit js-requires-input js-edit-blob-form') do
diff --git a/app/views/projects/builds/index.html.haml b/app/views/projects/builds/index.html.haml
index a131289ee97..381b3754cd5 100644
--- a/app/views/projects/builds/index.html.haml
+++ b/app/views/projects/builds/index.html.haml
@@ -31,7 +31,7 @@
data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post
- unless @repository.gitlab_ci_yml
- = link_to 'Get started with Builds', help_page_path('ci/quick_start', 'README'), class: 'btn btn-info'
+ = link_to 'Get started with Builds', help_page_path('ci/quick_start/README'), class: 'btn btn-info'
= link_to ci_lint_path, class: 'btn btn-default' do
%span CI Lint
diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml
index d1c468c4692..4421f3b9562 100644
--- a/app/views/projects/builds/show.html.haml
+++ b/app/views/projects/builds/show.html.haml
@@ -67,4 +67,4 @@
= render "sidebar"
:javascript
- new CiBuild("#{namespace_project_build_url(@project.namespace, @project, @build, :json)}", "#{@build.status}", "#{trace_with_state[:state]}")
+ new Build("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{namespace_project_build_url(@project.namespace, @project, @build, :json)}", "#{@build.status}", "#{trace_with_state[:state]}")
diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml
index 34ad9fe2c43..a9eaed4c5f6 100644
--- a/app/views/projects/buttons/_fork.html.haml
+++ b/app/views/projects/buttons/_fork.html.haml
@@ -14,6 +14,5 @@
Fork
%div.count-with-arrow
%span.arrow
- %span.count
- = link_to namespace_project_forks_path(@project.namespace, @project) do
- = @project.forks_count
+ = link_to namespace_project_forks_path(@project.namespace, @project), class: "count" do
+ = @project.forks_count
diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml
index e38d1ff5ff0..af8dd5cd02c 100644
--- a/app/views/projects/ci/pipelines/_pipeline.html.haml
+++ b/app/views/projects/ci/pipelines/_pipeline.html.haml
@@ -45,7 +45,7 @@
%td
- if pipeline.started_at && pipeline.finished_at
%p.duration
- #{duration_in_words(pipeline.finished_at, pipeline.started_at)}
+ = duration_in_numbers(pipeline.finished_at, pipeline.started_at)
%td
.controls.hidden-xs.pull-right
diff --git a/app/views/projects/commit/_ci_stage.html.haml b/app/views/projects/commit/_ci_stage.html.haml
index ae7bb01223e..9d925cacc0d 100644
--- a/app/views/projects/commit/_ci_stage.html.haml
+++ b/app/views/projects/commit/_ci_stage.html.haml
@@ -7,7 +7,7 @@
= ci_icon_for_status(status)
- if stage
&nbsp;
- = stage.titleize.pluralize
+ = stage.titleize
= render statuses.latest.ordered, coverage: @project.build_coverage_enabled?, stage: false, ref: false, allow_retry: true
= render statuses.retried.ordered, coverage: @project.build_coverage_enabled?, stage: false, ref: false, retried: true
%tr
diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml
index 401cb4f7e30..d0da2606587 100644
--- a/app/views/projects/commit/show.html.haml
+++ b/app/views/projects/commit/show.html.haml
@@ -7,8 +7,7 @@
= render "ci_menu"
- else
%div.block-connector
-= render "projects/diffs/diffs", diffs: @diffs, project: @project,
- diff_refs: @diff_refs
+= render "projects/diffs/diffs", diffs: @diffs, project: @project, diff_refs: @commit.diff_refs
= render "projects/notes/notes_with_form"
- if can_collaborate_with_project?
- %w(revert cherry-pick).each do |type|
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 929496f81d8..c8c7b858baa 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -25,7 +25,7 @@
.commit-actions.hidden-xs
- if commit.status
= render_commit_status(commit, cssclass: 'btn btn-transparent')
- = clipboard_button_with_class({ clipboard_text: commit.id }, css_class: 'btn-transparent')
+ = clipboard_button(clipboard_text: commit.id)
= link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit-short-id btn btn-transparent"
= link_to_browse_code(project, commit)
diff --git a/app/views/projects/deploy_keys/_form.html.haml b/app/views/projects/deploy_keys/_form.html.haml
index 894c36a96df..901605f7ca3 100644
--- a/app/views/projects/deploy_keys/_form.html.haml
+++ b/app/views/projects/deploy_keys/_form.html.haml
@@ -9,5 +9,5 @@
.form-group
%p.light.append-bottom-0
Paste a machine public key here. Read more about how to generate it
- = link_to "here", help_page_path("ssh", "README")
+ = link_to "here", help_page_path("ssh/README")
= f.submit "Add key", class: "btn-create btn"
diff --git a/app/views/projects/diffs/_content.html.haml b/app/views/projects/diffs/_content.html.haml
new file mode 100644
index 00000000000..0c0424edffd
--- /dev/null
+++ b/app/views/projects/diffs/_content.html.haml
@@ -0,0 +1,29 @@
+.diff-content.diff-wrap-lines
+ - # Skip all non non-supported blobs
+ - return unless blob.respond_to?(:text?)
+ - if diff_file.too_large?
+ .nothing-here-block This diff could not be displayed because it is too large.
+ - elsif blob.only_display_raw?
+ .nothing-here-block This file is too large to display.
+ - elsif blob_text_viewable?(blob)
+ - if !project.repository.diffable?(blob)
+ .nothing-here-block This diff was suppressed by a .gitattributes entry.
+ - elsif diff_file.diff_lines.length > 0
+ - if diff_file.collapsed_by_default? && !expand_all_diffs?
+ - url = url_for(params.merge(action: :diff_for_path, old_path: diff_file.old_path, new_path: diff_file.new_path))
+ .nothing-here-block.diff-collapsed{data: { diff_for_path: url } }
+ This diff is collapsed. Click to expand it.
+ - elsif diff_view == 'parallel'
+ = render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob
+ - else
+ = render "projects/diffs/text_file", diff_file: diff_file
+ - else
+ - if diff_file.mode_changed?
+ .nothing-here-block File mode changed
+ - elsif diff_file.renamed_file
+ .nothing-here-block File moved
+ - elsif blob.image?
+ - old_blob = diff_file.old_blob(diff_commit)
+ = render "projects/diffs/image", diff_file: diff_file, old_file: old_blob, file: blob
+ - else
+ .nothing-here-block No preview for this file type
diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml
index f18bc8c41b3..20aaab5accf 100644
--- a/app/views/projects/diffs/_diffs.html.haml
+++ b/app/views/projects/diffs/_diffs.html.haml
@@ -2,10 +2,12 @@
- if diff_view == 'parallel'
- fluid_layout true
-- diff_files = safe_diff_files(diffs, diff_refs)
+- diff_files = safe_diff_files(diffs, diff_refs: diff_refs, repository: project.repository)
.content-block.oneline-block.files-changed
.inline-parallel-buttons
+ - unless expand_all_diffs?
+ = link_to 'Expand all', url_for(params.merge(expand_all_diffs: 1, format: 'html')), class: 'btn btn-default'
- if show_whitespace_toggle
- if current_controller?(:commit)
= commit_diff_whitespace_link(@project, @commit, class: 'hidden-xs')
@@ -21,10 +23,10 @@
- if diff_files.overflow?
= render 'projects/diffs/warning', diff_files: diff_files
-.files
+.files{data: {can_create_note: (!@diff_notes_disabled && can?(current_user, :create_note, @project))}}
- diff_files.each_with_index do |diff_file, index|
- diff_commit = commit_for_diff(diff_file)
- - blob = project.repository.blob_for_diff(diff_commit, diff_file)
+ - blob = diff_file.blob(diff_commit)
- next unless blob
- blob.load_all_data!(project.repository) unless blob.only_display_raw?
diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml
index 2395ea3c275..c306909fb1a 100644
--- a/app/views/projects/diffs/_file.html.haml
+++ b/app/views/projects/diffs/_file.html.haml
@@ -1,29 +1,8 @@
-.diff-file.file-holder{id: "diff-#{i}", data: diff_file_html_data(project, diff_commit, diff_file)}
+.diff-file.file-holder{id: "diff-#{i}", data: diff_file_html_data(project, diff_file)}
.file-title{id: "file-path-#{hexdigest(diff_file.file_path)}"}
- - if diff_file.diff.submodule?
- %span
- = icon('archive fw')
- %span
- = submodule_link(blob, @commit.id, project.repository)
- - else
- = blob_icon blob.mode, blob.name
-
- = link_to "#diff-#{i}" do
- - if diff_file.renamed_file
- - old_path, new_path = mark_inline_diffs(diff_file.old_path, diff_file.new_path)
- = old_path
- &rarr;
- = new_path
- - else
- %span
- = diff_file.new_path
- - if diff_file.deleted_file
- deleted
-
- - if diff_file.mode_changed?
- %small
- = "#{diff_file.diff.a_mode} → #{diff_file.diff.b_mode}"
+ = render "projects/diffs/file_header", diff_file: diff_file, blob: blob, diff_commit: diff_commit, project: project, url: "#diff-#{i}"
+ - unless diff_file.submodule?
.file-actions.hidden-xs
- if blob_text_viewable?(blob)
= link_to '#', class: 'js-toggle-diff-comments btn active has-tooltip btn-file-option', title: "Toggle comments for this file" do
@@ -37,22 +16,4 @@
= view_file_btn(diff_commit.id, diff_file, project)
- .diff-content.diff-wrap-lines
- - # Skip all non non-supported blobs
- - return unless blob.respond_to?(:text?)
- - if diff_file.too_large?
- .nothing-here-block This diff could not be displayed because it is too large.
- - elsif blob_text_viewable?(blob) && !project.repository.diffable?(blob)
- .nothing-here-block This diff was suppressed by a .gitattributes entry.
- - elsif blob_text_viewable?(blob)
- - if diff_view == 'parallel'
- = render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob, index: i
- - else
- = render "projects/diffs/text_file", diff_file: diff_file, index: i
- - elsif blob.only_display_raw?
- .nothing-here-block This file is too large to display.
- - elsif blob.image?
- - old_file = project.repository.prev_blob_for_diff(diff_commit, diff_file)
- = render "projects/diffs/image", diff_file: diff_file, old_file: old_file, file: blob, index: i, diff_refs: diff_refs
- - else
- .nothing-here-block No preview for this file type
+ = render 'projects/diffs/content', diff_file: diff_file, diff_commit: diff_commit, diff_refs: diff_refs, blob: blob, project: project
diff --git a/app/views/projects/diffs/_file_header.html.haml b/app/views/projects/diffs/_file_header.html.haml
new file mode 100644
index 00000000000..95a2772fd0b
--- /dev/null
+++ b/app/views/projects/diffs/_file_header.html.haml
@@ -0,0 +1,25 @@
+- if defined?(blob) && blob && diff_file.submodule?
+ %span
+ = icon('archive fw')
+ %span
+ = submodule_link(blob, diff_commit.id, project.repository)
+- else
+ = conditional_link_to url.present?, url do
+ = blob_icon diff_file.b_mode, diff_file.file_path
+
+ - if diff_file.renamed_file
+ - old_path, new_path = mark_inline_diffs(diff_file.old_path, diff_file.new_path)
+ %strong
+ = old_path
+ &rarr;
+ %strong
+ = new_path
+ - else
+ %strong
+ = diff_file.new_path
+ - if diff_file.deleted_file
+ deleted
+
+ - if diff_file.mode_changed?
+ %small
+ = "#{diff_file.a_mode} → #{diff_file.b_mode}"
diff --git a/app/views/projects/diffs/_image.html.haml b/app/views/projects/diffs/_image.html.haml
index 2731219ccad..9ec6a7aa5cd 100644
--- a/app/views/projects/diffs/_image.html.haml
+++ b/app/views/projects/diffs/_image.html.haml
@@ -1,9 +1,8 @@
- diff = diff_file.diff
-- file_raw_path = namespace_project_raw_path(@project.namespace, @project, tree_join(@commit.id, diff.new_path))
+- file_raw_path = namespace_project_raw_path(@project.namespace, @project, tree_join(diff_file.new_ref, diff.new_path))
// diff_refs will be nil for orphaned commits (e.g. first commit in repo)
-- if diff_refs
- - old_commit_id = diff_refs.first.id
- - old_file_raw_path = namespace_project_raw_path(@project.namespace, @project, tree_join(old_commit_id, diff.old_path))
+- if diff_file.old_ref
+ - old_file_raw_path = namespace_project_raw_path(@project.namespace, @project, tree_join(diff_file.old_ref, diff.old_path))
- if diff.renamed_file || diff.new_file || diff.deleted_file
.image
@@ -16,7 +15,7 @@
%div.two-up.view
%span.wrap
.frame.deleted
- %a{href: namespace_project_blob_path(@project.namespace, @project, tree_join(old_commit_id, diff.old_path))}
+ %a{href: namespace_project_blob_path(@project.namespace, @project, tree_join(diff_file.old_ref, diff.old_path))}
%img{src: old_file_raw_path}
%p.image-info.hide
%span.meta-filesize= "#{number_to_human_size old_file.size}"
@@ -28,7 +27,7 @@
%span.meta-height
%span.wrap
.frame.added
- %a{href: namespace_project_blob_path(@project.namespace, @project, tree_join(@commit.id, diff.new_path))}
+ %a{href: namespace_project_blob_path(@project.namespace, @project, tree_join(diff_file.new_ref, diff.new_path))}
%img{src: file_raw_path}
%p.image-info.hide
%span.meta-filesize= "#{number_to_human_size file.size}"
diff --git a/app/views/projects/diffs/_line.html.haml b/app/views/projects/diffs/_line.html.haml
index f1577e8a47b..5a8a131d10c 100644
--- a/app/views/projects/diffs/_line.html.haml
+++ b/app/views/projects/diffs/_line.html.haml
@@ -1,3 +1,6 @@
+- plain = local_assigns.fetch(:plain, false)
+- line_code = diff_file.line_code(line)
+- position = diff_file.position(line)
- type = line.type
%tr.line_holder{ id: line_code, class: type }
- case type
@@ -9,18 +12,16 @@
%td.new_line.diff-line-num
%td.line_content.match= line.text
- else
- %td.old_line.diff-line-num{ class: type, data: { linenumber: line.new_pos } }
- - link_text = type == "new" ? "&nbsp;".html_safe : line.old_pos
- - if defined?(plain) && plain
+ %td.old_line.diff-line-num{ class: type, data: { linenumber: line.old_pos } }
+ - link_text = type == "new" ? " " : line.old_pos
+ - if plain
= link_text
- else
- = link_to "", "##{line_code}", id: line_code, data: { linenumber: link_text }
- - if !@diff_notes_disabled && can?(current_user, :create_note, @project)
- = link_to_new_diff_note(line_code)
+ %a{href: "##{line_code}", data: { linenumber: link_text }}
%td.new_line.diff-line-num{ class: type, data: { linenumber: line.new_pos } }
- - link_text = type == "old" ? "&nbsp;".html_safe : line.new_pos
- - if defined?(plain) && plain
+ - link_text = type == "old" ? " " : line.new_pos
+ - if plain
= link_text
- else
- = link_to "", "##{line_code}", id: line_code, data: { linenumber: link_text }
- %td.line_content{ class: ['noteable_line', type, line_code], data: { line_code: line_code } }= diff_line_content(line.text, type)
+ %a{href: "##{line_code}", data: { linenumber: link_text }}
+ %td.line_content.noteable_line{ class: type, data: (diff_view_line_data(line_code, position, type) unless plain) }= diff_line_content(line.text, type)
diff --git a/app/views/projects/diffs/_match_line_parallel.html.haml b/app/views/projects/diffs/_match_line_parallel.html.haml
index 0cd888876e0..b9c0d9dcdfd 100644
--- a/app/views/projects/diffs/_match_line_parallel.html.haml
+++ b/app/views/projects/diffs/_match_line_parallel.html.haml
@@ -1,4 +1,4 @@
-%td.old_line.diff-line-num
+%td.old_line.diff-line-num.empty-cell
%td.line_content.parallel.match= line
-%td.new_line.diff-line-num
+%td.new_line.diff-line-num.empty-cell
%td.line_content.parallel.match= line
diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml
index 4ecc9528bd2..d208fcee10b 100644
--- a/app/views/projects/diffs/_parallel_view.html.haml
+++ b/app/views/projects/diffs/_parallel_view.html.haml
@@ -1,43 +1,36 @@
/ Side-by-side diff view
-%div.text-file.diff-wrap-lines.code.file-content.js-syntax-highlight
+%div.text-file.diff-wrap-lines.code.file-content.js-syntax-highlight{ data: diff_view_data }
%table
- diff_file.parallel_diff_lines.each do |line|
- left = line[:left]
- right = line[:right]
%tr.line_holder.parallel
- if left[:type] == 'match'
- = render "projects/diffs/match_line_parallel", { line: left[:text],
- line_old: left[:number], line_new: right[:number] }
+ = render "projects/diffs/match_line_parallel", { line: left[:text] }
- elsif left[:type] == 'nonewline'
- %td.old_line.diff-line-num
+ %td.old_line.diff-line-num.empty-cell
%td.line_content.parallel.match= left[:text]
- %td.new_line.diff-line-num
+ %td.new_line.diff-line-num.empty-cell
%td.line_content.parallel.match= left[:text]
- else
- %td.old_line.diff-line-num{id: left[:line_code], class: "#{left[:type]} #{'empty-cell' if !left[:number]}"}
- = link_to raw(left[:number]), "##{left[:line_code]}", id: left[:line_code]
- - if !@diff_notes_disabled && can?(current_user, :create_note, @project)
- = link_to_new_diff_note(left[:line_code], 'old')
- %td.line_content{class: "parallel noteable_line #{left[:type]} #{left[:line_code]} #{'empty-cell' if left[:text].empty?}", data: { line_code: left[:line_code] }}= diff_line_content(left[:text])
+ %td.old_line.diff-line-num{id: left[:line_code], class: [left[:type], ('empty-cell' unless left[:number])], data: { linenumber: left[:number] }}
+ %a{href: "##{left[:line_code]}" }= raw(left[:number])
+ %td.line_content.parallel.noteable_line{class: [left[:type], ('empty-cell' if left[:text].empty?)], data: diff_view_line_data(left[:line_code], left[:position], 'old')}= diff_line_content(left[:text])
- if right[:type] == 'new'
- - new_line_class = 'new'
+ - new_line_type = 'new'
- new_line_code = right[:line_code]
+ - new_position = right[:position]
- else
- - new_line_class = nil
+ - new_line_type = nil
- new_line_code = left[:line_code]
+ - new_position = left[:position]
- %td.new_line.diff-line-num{id: new_line_code, class: "#{new_line_class} #{'empty-cell' if !right[:number]}", data: { linenumber: right[:number] }}
- = link_to raw(right[:number]), "##{new_line_code}", id: new_line_code
- - if !@diff_notes_disabled && can?(current_user, :create_note, @project)
- = link_to_new_diff_note(new_line_code, 'new')
- %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code} #{'empty-cell' if right[:text].empty?}", data: { line_code: new_line_code }}= diff_line_content(right[:text])
+ %td.new_line.diff-line-num{id: new_line_code, class: [new_line_type, ('empty-cell' unless right[:number])], data: { linenumber: right[:number] }}
+ %a{href: "##{new_line_code}" }= raw(right[:number])
+ %td.line_content.parallel.noteable_line{class: [new_line_type, ('empty-cell' if right[:text].empty?)], data: diff_view_line_data(new_line_code, new_position, 'new')}= diff_line_content(right[:text])
- unless @diff_notes_disabled
- notes_left, notes_right = organize_comments(left, right)
- if notes_left.present? || notes_right.present?
= render "projects/notes/diff_notes_with_reply_parallel", notes_left: notes_left, notes_right: notes_right
-
-- if diff_file.diff.diff.blank? && diff_file.mode_changed?
- .file-mode-changed
- File mode changed
diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml
index 068593a7dd1..196f8122db3 100644
--- a/app/views/projects/diffs/_text_file.html.haml
+++ b/app/views/projects/diffs/_text_file.html.haml
@@ -3,23 +3,18 @@
.suppressed-container
%a.show-suppressed-diff.js-show-suppressed-diff Changes suppressed. Click to show.
-%table.text-file.code.js-syntax-highlight{ class: too_big ? 'hide' : '' }
-
+%table.text-file.code.js-syntax-highlight{ data: diff_view_data, class: too_big ? 'hide' : '' }
- last_line = 0
- - diff_file.highlighted_diff_lines.each_with_index do |line, index|
- - line_code = generate_line_code(diff_file.file_path, line)
+ - diff_file.highlighted_diff_lines.each do |line|
- last_line = line.new_pos
- = render "projects/diffs/line", {line: line, diff_file: diff_file, line_code: line_code}
+ = render "projects/diffs/line", line: line, diff_file: diff_file
- unless @diff_notes_disabled
- - diff_notes = @grouped_diff_notes[line_code]
+ - line_code = diff_file.line_code(line)
+ - diff_notes = @grouped_diff_notes[line_code] if line_code
- if diff_notes
= render "projects/notes/diff_notes_with_reply", notes: diff_notes
- if last_line > 0
= render "projects/diffs/match_line", { line: "",
line_old: last_line, line_new: last_line, bottom: true, new_file: diff_file.new_file }
-
-- if diff_file.diff.blank? && diff_file.mode_changed?
- .file-mode-changed
- File mode changed
diff --git a/app/views/projects/diffs/_warning.html.haml b/app/views/projects/diffs/_warning.html.haml
index 15536c17f8e..10fa1ddf2e5 100644
--- a/app/views/projects/diffs/_warning.html.haml
+++ b/app/views/projects/diffs/_warning.html.haml
@@ -2,9 +2,6 @@
%h4
Too many changes to show.
.pull-right
- - unless diff_hard_limit_enabled?
- = link_to "Reload with full diff", url_for(params.merge(force_show_diff: true, format: nil)), class: "btn btn-sm"
-
- if current_controller?(:commit) or current_controller?(:merge_requests)
- if current_controller?(:commit)
= link_to "Plain diff", namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff), class: "btn btn-sm"
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 27a94fe02dc..57af167180b 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -23,7 +23,7 @@
.form-group.project-visibility-level-holder
= f.label :visibility_level, class: 'label-light' do
Visibility Level
- = link_to "(?)", help_page_path("public_access", "public_access")
+ = link_to "(?)", help_page_path("public_access/public_access")
- if can_change_visibility_level?(@project, current_user)
= render('shared/visibility_radios', model_method: :visibility_level, form: f, selected_level: @project.visibility_level, form_model: @project)
- else
diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml
index 5242021243e..303d7c23d01 100644
--- a/app/views/projects/environments/index.html.haml
+++ b/app/views/projects/environments/index.html.haml
@@ -17,7 +17,7 @@
Environments are places where code gets deployed, such as staging or production.
%br
= succeed "." do
- = link_to "Read more about environments", help_page_path("ci", "environments")
+ = link_to "Read more about environments", help_page_path("ci/environments")
- if can?(current_user, :create_environment, @project)
= link_to new_namespace_project_environment_path(@project.namespace, @project), class: 'btn btn-create' do
New environment
diff --git a/app/views/projects/environments/new.html.haml b/app/views/projects/environments/new.html.haml
index da325efecd2..89e06567196 100644
--- a/app/views/projects/environments/new.html.haml
+++ b/app/views/projects/environments/new.html.haml
@@ -7,6 +7,6 @@
%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 about environments", help_page_path("ci/environments")
= render 'form'
diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml
index 53c62ef234d..b17aba2431f 100644
--- a/app/views/projects/environments/show.html.haml
+++ b/app/views/projects/environments/show.html.haml
@@ -20,7 +20,7 @@
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"
+ = link_to "Read more", help_page_path("ci/environments"), class: "btn btn-success"
- else
.table-holder
%table.table.environments
diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml
index 7ce4c1e5555..312bd86ed04 100644
--- a/app/views/projects/issues/index.html.haml
+++ b/app/views/projects/issues/index.html.haml
@@ -6,21 +6,37 @@
- if current_user
= auto_discovery_link_tag(:atom, namespace_project_issues_url(@project.namespace, @project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues")
-%div{ class: container_class }
- .top-area
- = render 'shared/issuable/nav', type: :issues
- .nav-controls
- - if current_user
- = link_to namespace_project_issues_path(@project.namespace, @project, :atom, { private_token: current_user.private_token }), class: 'btn append-right-10' do
- = icon('rss')
- %span.icon-label
- Subscribe
- = render 'shared/issuable/search_form', path: namespace_project_issues_path(@project.namespace, @project)
+%div{ class: (container_class) }
+ - if @project.issues.any?
+ .top-area
+ = render 'shared/issuable/nav', type: :issues
+ .nav-controls
+ - if current_user
+ = link_to namespace_project_issues_path(@project.namespace, @project, :atom, { private_token: current_user.private_token }), class: 'btn append-right-10' do
+ = icon('rss')
+ %span.icon-label
+ Subscribe
+ = render 'shared/issuable/search_form', path: namespace_project_issues_path(@project.namespace, @project)
+ - if can? current_user, :create_issue, @project
+ = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { assignee_id: @issuable_finder.assignee.try(:id), milestone_id: @issuable_finder.milestones.try(:first).try(:id) }), class: "btn btn-new", title: "New Issue", id: "new_issue_link" do
+ New Issue
+ = render 'shared/issuable/filter', type: :issues
+
+ .issues-holder
+ = render "issues"
+ - else
+ .blank-state.blank-state-welcome
+ %h2.blank-state-title.blank-state-welcome-title
+ Welcome to GitLab Issues
+ %p.blank-state-text
+ Code, test, and deploy together
+ .blank-state
+ .blank-state-icon
+ = navbar_icon("issues", size: 50)
+ %h3.blank-state-title
+ You don't have any issues right now.
+ %p.blank-state-text
+ Issues are the best way to track your project progress
- if can? current_user, :create_issue, @project
- = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { assignee_id: @issuable_finder.assignee.try(:id), milestone_id: @issuable_finder.milestones.try(:first).try(:id) }), class: "btn btn-new", title: "New Issue", id: "new_issue_link" do
+ = link_to new_namespace_project_issue_path(@project.namespace, @project), class: "btn btn-new", title: "New Issue", id: "new_issue_link" do
New Issue
-
- = render 'shared/issuable/filter', type: :issues
-
- .issues-holder
- = render "issues"
diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml
index 2ec96308fd7..873ed9b59ee 100644
--- a/app/views/projects/merge_requests/_show.html.haml
+++ b/app/views/projects/merge_requests/_show.html.haml
@@ -42,7 +42,7 @@
= succeed '.' do
= link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal"
- - if @commits.present?
+ - if @commits_count.nonzero?
%ul.merge-request-tabs.nav-links.no-top.no-bottom
%li.notes-tab
= link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#notes', action: 'notes', toggle: 'tab'} do
@@ -51,7 +51,7 @@
%li.commits-tab
= link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#commits', action: 'commits', toggle: 'tab'} do
Commits
- %span.badge= @commits.size
+ %span.badge= @commits_count
- if @pipeline
%li.builds-tab
= link_to builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#builds', action: 'builds', toggle: 'tab'} do
diff --git a/app/views/projects/merge_requests/show/_how_to_merge.html.haml b/app/views/projects/merge_requests/show/_how_to_merge.html.haml
index b3bea900d42..b727efaa6a6 100644
--- a/app/views/projects/merge_requests/show/_how_to_merge.html.haml
+++ b/app/views/projects/merge_requests/show/_how_to_merge.html.haml
@@ -8,7 +8,7 @@
%p
%strong Step 1.
Fetch and check out the branch for this merge request
- = clipboard_button_with_class({clipboard_target: "pre#merge-info-1"}, css_class: "btn-clipboard")
+ = clipboard_button(clipboard_target: "pre#merge-info-1")
%pre.dark#merge-info-1
- if @merge_request.for_fork?
:preserve
@@ -25,7 +25,7 @@
%p
%strong Step 3.
Merge the branch and fix any conflicts that come up
- = clipboard_button_with_class({clipboard_target: "pre#merge-info-3"}, css_class: "btn-clipboard")
+ = clipboard_button(clipboard_target: "pre#merge-info-3")
%pre.dark#merge-info-3
- if @merge_request.for_fork?
:preserve
@@ -38,7 +38,7 @@
%p
%strong Step 4.
Push the result of the merge to GitLab
- = clipboard_button_with_class({clipboard_target: "pre#merge-info-4"}, css_class: "btn-clipboard")
+ = clipboard_button(clipboard_target: "pre#merge-info-4")
%pre.dark#merge-info-4
:preserve
git push origin #{h @merge_request.target_branch}
diff --git a/app/views/projects/merge_requests/show/_mr_title.html.haml b/app/views/projects/merge_requests/show/_mr_title.html.haml
index 5bf5210aeab..b24bdf22ceb 100644
--- a/app/views/projects/merge_requests/show/_mr_title.html.haml
+++ b/app/views/projects/merge_requests/show/_mr_title.html.haml
@@ -19,13 +19,13 @@
Options
.dropdown-menu.dropdown-menu-align-right.hidden-lg
%ul
- %li{ class: issue_button_visibility(@merge_request, true) }
+ %li{ class: merge_request_button_visibility(@merge_request, true) }
= link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, title: 'Close merge request'
- %li{ class: issue_button_visibility(@merge_request, false) }
+ %li{ class: merge_request_button_visibility(@merge_request, false) }
= link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: 'reopen-mr-link', title: 'Reopen merge request'
%li
= link_to 'Edit', edit_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: 'issuable-edit'
- = link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, class: "hidden-xs hidden-sm btn btn-grouped btn-close #{issue_button_visibility(@merge_request, true)}", title: 'Close merge request'
- = link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "hidden-xs hidden-sm btn btn-grouped btn-reopen reopen-mr-link #{issue_button_visibility(@merge_request, false)}", title: 'Reopen merge request'
+ = link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, class: "hidden-xs hidden-sm btn btn-grouped btn-close #{merge_request_button_visibility(@merge_request, true)}", title: 'Close merge request'
+ = link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "hidden-xs hidden-sm btn btn-grouped btn-reopen reopen-mr-link #{merge_request_button_visibility(@merge_request, false)}", title: 'Reopen merge request'
= link_to edit_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: "hidden-xs hidden-sm btn btn-grouped issuable-edit" do
Edit
diff --git a/app/views/projects/merge_requests/widget/_heading.html.haml b/app/views/projects/merge_requests/widget/_heading.html.haml
index 08a38d283d2..489c632ae22 100644
--- a/app/views/projects/merge_requests/widget/_heading.html.haml
+++ b/app/views/projects/merge_requests/widget/_heading.html.haml
@@ -7,7 +7,7 @@
CI build
= ci_label_for_status(status)
for
- - commit = @merge_request.last_commit
+ - commit = @merge_request.diff_head_commit
= succeed "." do
= link_to @pipeline.short_sha, namespace_project_commit_path(@merge_request.source_project.namespace, @merge_request.source_project, @pipeline.sha), class: "monospace"
%span.ci-coverage
@@ -24,7 +24,7 @@
CI build
= ci_label_for_status(status)
for
- - commit = @merge_request.last_commit
+ - commit = @merge_request.diff_head_commit
= succeed "." do
= link_to commit.short_id, namespace_project_commit_path(@merge_request.source_project.namespace, @merge_request.source_project, commit), class: "monospace"
%span.ci-coverage
@@ -33,12 +33,12 @@
.ci_widget
= icon("spinner spin")
- Checking CI status for #{@merge_request.last_commit_short_sha}&hellip;
+ Checking CI status for #{@merge_request.diff_head_commit.short_id}&hellip;
.ci_widget.ci-not_found{style: "display:none"}
= icon("times-circle")
- Could not find CI status for #{@merge_request.last_commit_short_sha}.
+ Could not find CI status for #{@merge_request.diff_head_commit.short_id}.
.ci_widget.ci-error{style: "display:none"}
= icon("times-circle")
- Could not connect to the CI server. Please check your settings and try again. \ No newline at end of file
+ Could not connect to the CI server. Please check your settings and try again.
diff --git a/app/views/projects/merge_requests/widget/_open.html.haml b/app/views/projects/merge_requests/widget/_open.html.haml
index 0e0af57d76e..dc18f715f25 100644
--- a/app/views/projects/merge_requests/widget/_open.html.haml
+++ b/app/views/projects/merge_requests/widget/_open.html.haml
@@ -22,10 +22,10 @@
- elsif @merge_request.can_be_merged?
= render 'projects/merge_requests/widget/open/accept'
- - if @closes_issues.present?
+ - if mr_closes_issues.present?
.mr-widget-footer
%span
%i.fa.fa-check
- Accepting this merge request will close #{"issue".pluralize(@closes_issues.size)}
+ Accepting this merge request will close #{"issue".pluralize(mr_closes_issues.size)}
= succeed '.' do
- != markdown issues_sentence(@closes_issues), pipeline: :gfm, author: @merge_request.author
+ != markdown issues_sentence(mr_closes_issues), pipeline: :gfm, author: @merge_request.author
diff --git a/app/views/projects/merge_requests/widget/open/_accept.html.haml b/app/views/projects/merge_requests/widget/open/_accept.html.haml
index 941513febbd..bf2e76f0083 100644
--- a/app/views/projects/merge_requests/widget/open/_accept.html.haml
+++ b/app/views/projects/merge_requests/widget/open/_accept.html.haml
@@ -2,7 +2,7 @@
= form_for [:merge, @project.namespace.becomes(Namespace), @project, @merge_request], remote: true, method: :post, html: { class: 'accept-mr-form js-quick-submit js-requires-input' } do |f|
= hidden_field_tag :authenticity_token, form_authenticity_token
- = hidden_field_tag :sha, @merge_request.source_sha
+ = hidden_field_tag :sha, @merge_request.diff_head_sha
.accept-merge-holder.clearfix.js-toggle-container
.clearfix
.accept-action
diff --git a/app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml b/app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml
index ad898ff153b..2b6b5e05e86 100644
--- a/app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml
+++ b/app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml
@@ -16,7 +16,7 @@
- if remove_source_branch_button || user_can_cancel_automatic_merge
.clearfix.prepend-top-10
- if remove_source_branch_button
- = link_to merge_namespace_project_merge_request_path(@merge_request.target_project.namespace, @merge_request.target_project, @merge_request, merge_when_build_succeeds: true, should_remove_source_branch: true, sha: @merge_request.source_sha), remote: true, method: :post, class: "btn btn-grouped btn-primary btn-sm remove_source_branch" do
+ = link_to merge_namespace_project_merge_request_path(@merge_request.target_project.namespace, @merge_request.target_project, @merge_request, merge_when_build_succeeds: true, should_remove_source_branch: true, sha: @merge_request.diff_head_sha), remote: true, method: :post, class: "btn btn-grouped btn-primary btn-sm remove_source_branch" do
= icon('times')
Remove Source Branch When Merged
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index 05f33b78a47..9b00bdedc27 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -107,7 +107,7 @@
.form-group.project-visibility-level-holder
= f.label :visibility_level, class: 'label-light' do
Visibility Level
- = link_to "(?)", help_page_path("public_access", "public_access")
+ = link_to "(?)", help_page_path("public_access/public_access")
= render('shared/visibility_radios', model_method: :visibility_level, form: f, selected_level: @project.visibility_level, form_model: @project)
= f.submit 'Create project', class: "btn btn-create project-submit", tabindex: 4
diff --git a/app/views/projects/notes/_diff_notes_with_reply.html.haml b/app/views/projects/notes/_diff_notes_with_reply.html.haml
index 8144c1ba49e..ec6c4938efc 100644
--- a/app/views/projects/notes/_diff_notes_with_reply.html.haml
+++ b/app/views/projects/notes/_diff_notes_with_reply.html.haml
@@ -4,5 +4,4 @@
%td.notes_content
%ul.notes{ data: { discussion_id: note.discussion_id } }
= render partial: "projects/notes/note", collection: notes, as: :note
- .discussion-reply-holder
- = link_to_reply_discussion(note)
+ = link_to_reply_discussion(note)
diff --git a/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml b/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml
index 45986b0d1e8..e50a4f86d03 100644
--- a/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml
+++ b/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml
@@ -8,8 +8,7 @@
%ul.notes{ data: { discussion_id: note_left.discussion_id } }
= render partial: "projects/notes/note", collection: notes_left, as: :note
- .discussion-reply-holder
- = link_to_reply_discussion(note_left, 'old')
+ = link_to_reply_discussion(note_left, 'old')
- else
%td.notes_line.old= ""
%td.notes_content.parallel.old= ""
@@ -20,8 +19,7 @@
%ul.notes{ data: { discussion_id: note_right.discussion_id } }
= render partial: "projects/notes/note", collection: notes_right, as: :note
- .discussion-reply-holder
- = link_to_reply_discussion(note_right, 'new')
+ = link_to_reply_discussion(note_right, 'new')
- else
%td.notes_line.new= ""
%td.notes_content.parallel.new= ""
diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml
index 03b3f6935d1..7c61ba750fe 100644
--- a/app/views/projects/notes/_form.html.haml
+++ b/app/views/projects/notes/_form.html.haml
@@ -7,6 +7,7 @@
= f.hidden_field :noteable_id
= f.hidden_field :noteable_type
= f.hidden_field :type
+ = f.hidden_field :position
= render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do
= render 'projects/zen', f: f, attr: :note, classes: 'note-textarea js-note-text', placeholder: "Write a comment or drag your files here..."
diff --git a/app/views/projects/notes/_hints.html.haml b/app/views/projects/notes/_hints.html.haml
index 7d1cbc62e86..25466e7562e 100644
--- a/app/views/projects/notes/_hints.html.haml
+++ b/app/views/projects/notes/_hints.html.haml
@@ -1,7 +1,7 @@
.comment-toolbar.clearfix
.toolbar-text
Styling with
- = link_to 'Markdown', help_page_path('markdown', 'markdown'), target: '_blank', tabindex: -1
+ = link_to 'Markdown', help_page_path('markdown/markdown'), target: '_blank', tabindex: -1
is supported
%button.toolbar-button.markdown-selector{ type: 'button', tabindex: '-1' }
= icon('file-image-o', class: 'toolbar-button-icon')
diff --git a/app/views/projects/notes/_notes_with_form.html.haml b/app/views/projects/notes/_notes_with_form.html.haml
index 1c39ce897a3..56d302fab82 100644
--- a/app/views/projects/notes/_notes_with_form.html.haml
+++ b/app/views/projects/notes/_notes_with_form.html.haml
@@ -2,6 +2,8 @@
= render "projects/notes/notes"
%ul.notes.notes-form.timeline
%li.timeline-entry
+ .flash-container.timeline-content
+
- if can? current_user, :create_note, @project
.timeline-icon.hidden-xs.hidden-sm
%a.author_link{ href: user_path(current_user) }
diff --git a/app/views/projects/notes/discussions/_diff_with_notes.html.haml b/app/views/projects/notes/discussions/_diff_with_notes.html.haml
index 6401245bf73..4a69b8f8840 100644
--- a/app/views/projects/notes/discussions/_diff_with_notes.html.haml
+++ b/app/views/projects/notes/discussions/_diff_with_notes.html.haml
@@ -1,30 +1,17 @@
- note = discussion_notes.first
-- diff = note.diff
-- return unless diff
+- diff_file = note.diff_file
+- return unless diff_file
+
+- blob = note.blob
+
+.diff-file.file-holder
+ .file-title
+ = render "projects/diffs/file_header", diff_file: diff_file, blob: blob, diff_commit: diff_file.content_commit, project: note.project, url: diff_note_path(note)
-.diff-file
- .diff-header
- %span
- - if diff.deleted_file
- = diff.old_path
- - else
- = diff.new_path
- - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
- %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}"
.diff-content.code.js-syntax-highlight
%table
- note.truncated_diff_lines.each do |line|
- - type = line.type
- - line_code = generate_line_code(note.diff_file_path, line)
- %tr.line_holder{ id: line_code, class: "#{type}" }
- - if type == "match"
- %td.old_line.diff-line-num= "..."
- %td.new_line.diff-line-num= "..."
- %td.line_content.match= line.text
- - else
- %td.old_line.diff-line-num{ data: { linenumber: type == "new" ? "&nbsp;".html_safe : line.old_pos } }
- %td.new_line.diff-line-num{ data: { linenumber: type == "old" ? "&nbsp;".html_safe : line.new_pos } }
- %td.line_content{ class: ['noteable_line', type, line_code], line_code: line_code }= diff_line_content(line.text, type)
+ = render "projects/diffs/line", line: line, diff_file: diff_file, plain: true
- - if line_code == note.line_code
- = render "projects/notes/diff_notes_with_reply", notes: discussion_notes
+ - if note.for_line?(line)
+ = render "projects/notes/diff_notes_with_reply", notes: discussion_notes
diff --git a/app/views/projects/notes/discussions/_notes.html.haml b/app/views/projects/notes/discussions/_notes.html.haml
index e598e3c7c63..a785149549d 100644
--- a/app/views/projects/notes/discussions/_notes.html.haml
+++ b/app/views/projects/notes/discussions/_notes.html.haml
@@ -3,5 +3,4 @@
.notes{ data: { discussion_id: note.discussion_id } }
%ul.notes.timeline
= render partial: "projects/notes/note", collection: discussion_notes, as: :note
- .discussion-reply-holder
- = link_to_reply_discussion(note)
+ = link_to_reply_discussion(note)
diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml
index 28b475d5c2f..7c225e2b282 100644
--- a/app/views/projects/pipelines/index.html.haml
+++ b/app/views/projects/pipelines/index.html.haml
@@ -31,7 +31,7 @@
New pipeline
- unless @repository.gitlab_ci_yml
- = link_to 'Get started with Pipelines', help_page_path('ci/quick_start', 'README'), class: 'btn btn-info'
+ = link_to 'Get started with Pipelines', help_page_path('ci/quick_start/README'), class: 'btn btn-info'
= link_to ci_lint_path, class: 'btn btn-default' do
%span CI Lint
@@ -50,7 +50,7 @@
- stages.each do |stage|
%th.stage
%span.has-tooltip{ title: "#{stage.titleize}" }
- = stage.titleize.pluralize
+ = stage.titleize
%th Duration
%th
= render @pipelines, commit_sha: true, stage: true, allow_retry: true, stages: stages
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 82892a33358..ea3d82d858e 100644
--- a/app/views/projects/project_members/_new_project_member.html.haml
+++ b/app/views/projects/project_members/_new_project_member.html.haml
@@ -12,7 +12,7 @@
= select_tag :access_level, options_for_select(ProjectMember.access_level_roles, @project_member.access_level), class: "project-access-select select2"
.help-block
Read more about role permissions
- %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink"
+ %strong= link_to "here", help_page_path("permissions/permissions"), class: "vlink"
.form-actions
= f.submit 'Add users to project', class: "btn btn-create"
diff --git a/app/views/projects/protected_branches/_branches_list.html.haml b/app/views/projects/protected_branches/_branches_list.html.haml
index 565905cbe7b..97cb1a9052b 100644
--- a/app/views/projects/protected_branches/_branches_list.html.haml
+++ b/app/views/projects/protected_branches/_branches_list.html.haml
@@ -1,6 +1,6 @@
%h5.prepend-top-0
- Already Protected (#{@branches.size})
-- if @branches.empty?
+ Already Protected (#{@protected_branches.size})
+- if @protected_branches.empty?
%p.settings-message.text-center
No branches are protected, protect a branch with the form above.
- else
@@ -9,33 +9,18 @@
%table.table.protected-branches-list
%colgroup
%col{ width: "30%" }
- %col{ width: "30%" }
+ %col{ width: "25%" }
%col{ width: "25%" }
- if can_admin_project
%col
%thead
%tr
- %th Branch
- %th Last commit
- %th Developers can push
+ %th Protected Branch
+ %th Commit
+ %th Developers Can Push
- if can_admin_project
%th
%tbody
- - @branches.each do |branch|
- - @url = namespace_project_protected_branch_path(@project.namespace, @project, branch)
- %tr
- %td
- = link_to(branch.name, namespace_project_commits_path(@project.namespace, @project, branch.name))
- - if @project.root_ref?(branch.name)
- %span.label.label-info.prepend-left-5 default
- %td
- - if commit = branch.commit
- = link_to(commit.short_id, namespace_project_commit_path(@project.namespace, @project, commit.id), class: 'commit_short_id')
- #{time_ago_with_tooltip(commit.committed_date)}
- - else
- (branch was removed from repository)
- %td
- = check_box_tag("developers_can_push", branch.id, branch.developers_can_push, data: { url: @url })
- - if can_admin_project
- %td
- = link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-warning btn-sm"
+ = render partial: @protected_branches, locals: { can_admin_project: can_admin_project }
+
+ = paginate @protected_branches, theme: 'gitlab'
diff --git a/app/views/projects/protected_branches/_dropdown.html.haml b/app/views/projects/protected_branches/_dropdown.html.haml
new file mode 100644
index 00000000000..b803d932e67
--- /dev/null
+++ b/app/views/projects/protected_branches/_dropdown.html.haml
@@ -0,0 +1,17 @@
+= f.hidden_field(:name)
+
+= dropdown_tag("Protected Branch",
+ options: { title: "Pick protected branch", toggle_class: 'js-protected-branch-select js-filter-submit',
+ filter: true, dropdown_class: "dropdown-menu-selectable", placeholder: "Search protected branches",
+ footer_content: true,
+ data: { show_no: true, show_any: true, show_upcoming: true,
+ selected: params[:protected_branch_name],
+ project_id: @project.try(:id) } }) do
+
+ %ul.dropdown-footer-list.hidden.protected-branch-select-footer-list
+ %li
+ = link_to '#', title: "New Protected Branch", class: "create-new-protected-branch" do
+ Create new
+
+:javascript
+ new ProtectedBranchSelect();
diff --git a/app/views/projects/protected_branches/_matching_branch.html.haml b/app/views/projects/protected_branches/_matching_branch.html.haml
new file mode 100644
index 00000000000..8a5332ca5bb
--- /dev/null
+++ b/app/views/projects/protected_branches/_matching_branch.html.haml
@@ -0,0 +1,9 @@
+%tr
+ %td
+ = link_to matching_branch.name, namespace_project_tree_path(@project.namespace, @project, matching_branch.name)
+ - if @project.root_ref?(matching_branch.name)
+ %span.label.label-info.prepend-left-5 default
+ %td
+ - commit = @project.commit(matching_branch.name)
+ = link_to(commit.short_id, namespace_project_commit_path(@project.namespace, @project, commit.id), class: 'commit_short_id')
+ = time_ago_with_tooltip(commit.committed_date)
diff --git a/app/views/projects/protected_branches/_protected_branch.html.haml b/app/views/projects/protected_branches/_protected_branch.html.haml
new file mode 100644
index 00000000000..474aec3a97c
--- /dev/null
+++ b/app/views/projects/protected_branches/_protected_branch.html.haml
@@ -0,0 +1,21 @@
+- url = namespace_project_protected_branch_path(@project.namespace, @project, protected_branch)
+%tr
+ %td
+ = protected_branch.name
+ - if @project.root_ref?(protected_branch.name)
+ %span.label.label-info.prepend-left-5 default
+ %td
+ - if protected_branch.wildcard?
+ - matching_branches = protected_branch.matching(repository.branches)
+ = link_to pluralize(matching_branches.count, "matching branch"), namespace_project_protected_branch_path(@project.namespace, @project, protected_branch)
+ - else
+ - if commit = protected_branch.commit
+ = link_to(commit.short_id, namespace_project_commit_path(@project.namespace, @project, commit.id), class: 'commit_short_id')
+ = time_ago_with_tooltip(commit.committed_date)
+ - else
+ (branch was removed from repository)
+ %td
+ = check_box_tag("developers_can_push", protected_branch.id, protected_branch.developers_can_push, data: { url: url })
+ - if can_admin_project
+ %td
+ = link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, protected_branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-warning btn-sm pull-right"
diff --git a/app/views/projects/protected_branches/index.html.haml b/app/views/projects/protected_branches/index.html.haml
index c7d317dbaee..3fab95751e0 100644
--- a/app/views/projects/protected_branches/index.html.haml
+++ b/app/views/projects/protected_branches/index.html.haml
@@ -4,30 +4,38 @@
.col-lg-3
%h4.prepend-top-0
= page_title
- %p Keep stable branches secure and force developers to use Merge Requests
- .col-lg-9
- %h5.prepend-top-0
- Protect a branch
- .account-well.append-bottom-default
- %p.light-header.append-bottom-0 Protected branches are designed to
+ %p Keep stable branches secure and force developers to use merge requests.
+ %p.prepend-top-20
+ Protected branches are designed to:
%ul
- %li prevent pushes from everybody except #{link_to "masters", help_page_path("permissions", "permissions"), class: "vlink"}
+ %li prevent pushes from everybody except #{link_to "masters", help_page_path("permissions/permissions"), class: "vlink"}
%li prevent anyone from force pushing to the branch
%li prevent anyone from deleting the branch
- %p.append-bottom-0 Read more about #{link_to "project permissions", help_page_path("permissions", "permissions"), class: "underlined-link"}
+ %p.append-bottom-0 Read more about #{link_to "project permissions", help_page_path("permissions/permissions"), class: "underlined-link"}
+ .col-lg-9
+ %h5.prepend-top-0
+ Protect a branch
- if can? current_user, :admin_project, @project
= form_for [@project.namespace.becomes(Namespace), @project, @protected_branch] do |f|
= form_errors(@protected_branch)
.form-group
= f.label :name, "Branch", class: "label-light"
- = f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , {include_blank: true}, {class: "select2", data: {placeholder: "Select branch"}})
+ = render partial: "dropdown", locals: { f: f }
+ %p.help-block
+ = link_to "Wildcards", help_page_path('workflow/protected_branches', anchor: "wildcard-protected-branches")
+ such as
+ %code *-stable
+ or
+ %code production/*
+ are supported.
+
.form-group
= f.check_box :developers_can_push, class: "pull-left"
.prepend-left-20
= f.label :developers_can_push, "Developers can push", class: "label-light append-bottom-0"
%p.light.append-bottom-0
Allow developers to push to this branch
- = f.submit "Protect", class: "btn-create btn"
+ = f.submit "Protect", class: "btn-create btn protect-branch-btn", disabled: true
%hr
= render "branches_list"
diff --git a/app/views/projects/protected_branches/show.html.haml b/app/views/projects/protected_branches/show.html.haml
new file mode 100644
index 00000000000..4d8169815b3
--- /dev/null
+++ b/app/views/projects/protected_branches/show.html.haml
@@ -0,0 +1,25 @@
+- page_title @protected_branch.name, "Protected Branches"
+
+.row.prepend-top-default.append-bottom-default
+ .col-lg-3
+ %h4.prepend-top-0
+ = @protected_branch.name
+
+ .col-lg-9
+ %h5 Matching Branches
+ - if @matching_branches.present?
+ .table-responsive
+ %table.table.protected-branches-list
+ %colgroup
+ %col{ width: "30%" }
+ %col{ width: "30%" }
+ %thead
+ %tr
+ %th Branch
+ %th Last commit
+ %tbody
+ - @matching_branches.each do |matching_branch|
+ = render partial: "matching_branch", object: matching_branch
+ - else
+ %p.settings-message.text-center
+ Couldn't find any matching branches.
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index f6e81af2638..dd1cf680cfa 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -12,60 +12,67 @@
= render 'projects/last_push'
= render "home_panel"
-.project-stats.row-content-block.second-block
- %div{ class: container_class }
- %ul.nav
- %li
- = link_to project_files_path(@project) do
- Files (#{repository_size})
- %li
- = link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do
- #{'Commit'.pluralize(@project.commit_count)} (#{number_with_delimiter(@project.commit_count)})
- %li
- = link_to namespace_project_branches_path(@project.namespace, @project) do
- #{'Branch'.pluralize(@repository.branch_count)} (#{number_with_delimiter(@repository.branch_count)})
+%nav.project-stats{ class: (container_class) }
+ %ul.nav
+ %li
+ = link_to project_files_path(@project) do
+ Files (#{repository_size})
+ %li
+ = link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do
+ #{'Commit'.pluralize(@project.commit_count)} (#{number_with_delimiter(@project.commit_count)})
+ %li
+ = link_to namespace_project_branches_path(@project.namespace, @project) do
+ #{'Branch'.pluralize(@repository.branch_count)} (#{number_with_delimiter(@repository.branch_count)})
+ %li
+ = link_to namespace_project_tags_path(@project.namespace, @project) do
+ #{'Tag'.pluralize(@repository.tag_count)} (#{number_with_delimiter(@repository.tag_count)})
+
+ - if default_project_view != 'readme' && @repository.readme
%li
- = link_to namespace_project_tags_path(@project.namespace, @project) do
- #{'Tag'.pluralize(@repository.tag_count)} (#{number_with_delimiter(@repository.tag_count)})
+ = link_to 'Readme', readme_path(@project)
- - if default_project_view != 'readme' && @repository.readme
- %li
- = link_to 'Readme', readme_path(@project)
+ - if @repository.changelog
+ %li
+ = link_to 'Changelog', changelog_path(@project)
- - if @repository.changelog
- %li
- = link_to 'Changelog', changelog_path(@project)
+ - if @repository.license_blob
+ %li
+ = link_to license_short_name(@project), license_path(@project)
- - if @repository.license_blob
- %li
- = link_to license_short_name(@project), license_path(@project)
+ - if @repository.contribution_guide
+ %li
+ = link_to 'Contribution guide', contribution_guide_path(@project)
- - if @repository.contribution_guide
- %li
- = link_to 'Contribution guide', contribution_guide_path(@project)
+ - if current_user && can_push_branch?(@project, @project.default_branch)
+ - unless @repository.changelog
+ %li.missing
+ = link_to add_special_file_path(@project, file_name: 'CHANGELOG') do
+ Add Changelog
+ - unless @repository.license_blob
+ %li.missing
+ = link_to add_special_file_path(@project, file_name: 'LICENSE') do
+ Add License
+ - unless @repository.contribution_guide
+ %li.missing
+ = link_to add_special_file_path(@project, file_name: 'CONTRIBUTING.md', commit_message: 'Add contribution guide') do
+ Add Contribution guide
+ - unless @repository.gitlab_ci_yml
+ %li.missing
+ = link_to add_special_file_path(@project, file_name: '.gitlab-ci.yml') do
+ Set Up CI
+ %li.project-repo-buttons-right
+ .project-repo-buttons.project-right-buttons
+ - if current_user
+ = render 'shared/members/access_request_buttons', source: @project
- - if current_user && can_push_branch?(@project, @project.default_branch)
- - unless @repository.changelog
- %li.missing
- = link_to add_special_file_path(@project, file_name: 'CHANGELOG') do
- Add Changelog
- - unless @repository.license_blob
- %li.missing
- = link_to add_special_file_path(@project, file_name: 'LICENSE') do
- Add License
- - unless @repository.contribution_guide
- %li.missing
- = link_to add_special_file_path(@project, file_name: 'CONTRIBUTING.md', commit_message: 'Add contribution guide') do
- Add Contribution guide
- - unless @repository.gitlab_ci_yml
- %li.missing
- = link_to add_special_file_path(@project, file_name: '.gitlab-ci.yml') do
- Set Up CI
+ .btn-group.project-repo-btn-group
+ = render "projects/buttons/download"
+ = render 'projects/buttons/dropdown'
+ = render 'shared/notifications/button', notification_setting: @notification_setting
- if @repository.commit
- .content-block.second-block.white
- %div{ class: container_class }
- = render 'projects/last_commit', commit: @repository.commit, project: @project
+ .project-last-commit{ class: container_class }
+ = render 'projects/last_commit', commit: @repository.commit, project: @project
%div{ class: container_class }
- if @project.archived?
@@ -75,4 +82,4 @@
Archived project! Repository is read-only
%div{class: "project-show-#{default_project_view}"}
- = render default_project_view
+ = render default_project_view \ No newline at end of file
diff --git a/app/views/projects/snippets/_actions.html.haml b/app/views/projects/snippets/_actions.html.haml
index bf57beb9d07..bdbf3e5f4d6 100644
--- a/app/views/projects/snippets/_actions.html.haml
+++ b/app/views/projects/snippets/_actions.html.haml
@@ -1,27 +1,29 @@
.hidden-xs
- = link_to new_namespace_project_snippet_path(@project.namespace, @project), class: 'btn btn-grouped btn-create new-snippet-link', title: "New Snippet" do
- = icon('plus')
- New Snippet
+ - if can?(current_user, :create_project_snippet, @project)
+ = link_to new_namespace_project_snippet_path(@project.namespace, @project), class: 'btn btn-grouped btn-create new-snippet-link', title: "New Snippet" do
+ New Snippet
- if can?(current_user, :update_project_snippet, @snippet)
= link_to edit_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-grouped snippable-edit" do
Edit
- if can?(current_user, :update_project_snippet, @snippet)
= link_to namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-warning", title: 'Delete Snippet' do
Delete
-.visible-xs-block.dropdown
- %button.btn.btn-default.btn-block.append-bottom-0.prepend-top-5{ data: { toggle: "dropdown" } }
- Options
- %span.caret
- .dropdown-menu.dropdown-menu-full-width
- %ul
- %li
- = link_to new_namespace_project_snippet_path(@project.namespace, @project), title: "New Snippet" do
- New Snippet
- - if can?(current_user, :update_project_snippet, @snippet)
- %li
- = link_to edit_namespace_project_snippet_path(@project.namespace, @project, @snippet) do
- Edit
- - if can?(current_user, :update_project_snippet, @snippet)
- %li
- = link_to namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, title: 'Delete Snippet' do
- Delete
+- if can?(current_user, :create_project_snippet, @project) || can?(current_user, :update_project_snippet, @snippet)
+ .visible-xs-block.dropdown
+ %button.btn.btn-default.btn-block.append-bottom-0.prepend-top-5{ data: { toggle: "dropdown" } }
+ Options
+ %span.caret
+ .dropdown-menu.dropdown-menu-full-width
+ %ul
+ - if can?(current_user, :create_project_snippet, @project)
+ %li
+ = link_to new_namespace_project_snippet_path(@project.namespace, @project), title: "New Snippet" do
+ New Snippet
+ - if can?(current_user, :update_project_snippet, @snippet)
+ %li
+ = link_to edit_namespace_project_snippet_path(@project.namespace, @project, @snippet) do
+ Edit
+ - if can?(current_user, :update_project_snippet, @snippet)
+ %li
+ = link_to namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, title: 'Delete Snippet' do
+ Delete
diff --git a/app/views/projects/snippets/index.html.haml b/app/views/projects/snippets/index.html.haml
index 96fee3b17b2..6c994ae486b 100644
--- a/app/views/projects/snippets/index.html.haml
+++ b/app/views/projects/snippets/index.html.haml
@@ -2,9 +2,9 @@
.row-content-block.top-block
.pull-right
- = link_to new_namespace_project_snippet_path(@project.namespace, @project), class: "btn btn-new", title: "New Snippet" do
- = icon('plus')
- New Snippet
+ - if can?(current_user, :create_project_snippet, @project)
+ = link_to new_namespace_project_snippet_path(@project.namespace, @project), class: "btn btn-new", title: "New Snippet" do
+ New Snippet
.oneline
Share code pastes with others out of git repository
diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml
index c375bb6dd1b..368231e73fe 100644
--- a/app/views/projects/tags/index.html.haml
+++ b/app/views/projects/tags/index.html.haml
@@ -7,22 +7,22 @@
.nav-text
Tags give the ability to mark specific points in history as being important
- - if can? current_user, :push_code, @project
- .nav-controls
+ .nav-controls
+ - if can? current_user, :push_code, @project
= link_to new_namespace_project_tag_path(@project.namespace, @project), class: 'btn btn-create new-tag-btn' do
New tag
- .dropdown.inline
- %button.dropdown-toggle.btn{ type: 'button', data: { toggle: 'dropdown'} }
- %span.light= @sort.humanize
- %b.caret
- %ul.dropdown-menu.dropdown-menu-align-right
- %li
- = link_to namespace_project_tags_path(sort: nil) do
- Name
- = link_to namespace_project_tags_path(sort: sort_value_recently_updated) do
- = sort_title_recently_updated
- = link_to namespace_project_tags_path(sort: sort_value_oldest_updated) do
- = sort_title_oldest_updated
+ .dropdown.inline
+ %button.dropdown-toggle.btn{ type: 'button', data: { toggle: 'dropdown'} }
+ %span.light= @sort.humanize
+ %b.caret
+ %ul.dropdown-menu.dropdown-menu-align-right
+ %li
+ = link_to namespace_project_tags_path(sort: nil) do
+ Name
+ = link_to namespace_project_tags_path(sort: sort_value_recently_updated) do
+ = sort_title_recently_updated
+ = link_to namespace_project_tags_path(sort: sort_value_oldest_updated) do
+ = sort_title_oldest_updated
.tags
- if @tags.any?
diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml
index 84b3f44c0ad..3b82d8e686f 100644
--- a/app/views/shared/_clone_panel.html.haml
+++ b/app/views/shared/_clone_panel.html.haml
@@ -2,15 +2,20 @@
.git-clone-holder.input-group
.input-group-btn
- %a#clone-dropdown.clone-dropdown-btn.btn{href: '#', 'data-toggle' => 'dropdown'}
- %span
- = default_clone_protocol.upcase
- = icon('caret-down')
- %ul.dropdown-menu.dropdown-menu-right.clone-options-dropdown
- %li
- = ssh_clone_button(project)
- %li
- = http_clone_button(project)
+ -if allowed_protocols_present?
+ .clone-dropdown-btn.btn.btn-static
+ %span
+ = enabled_project_button(project, enabled_protocol)
+ - else
+ %a#clone-dropdown.clone-dropdown-btn.btn{href: '#', data: { toggle: 'dropdown' }}
+ %span
+ = default_clone_protocol.upcase
+ = icon('caret-down')
+ %ul.dropdown-menu.dropdown-menu-right.clone-options-dropdown
+ %li
+ = ssh_clone_button(project)
+ %li
+ = http_clone_button(project)
= text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true
.input-group-btn
diff --git a/app/views/shared/_labels_row.html.haml b/app/views/shared/_labels_row.html.haml
index 5507a05f6c1..dce492352ac 100644
--- a/app/views/shared/_labels_row.html.haml
+++ b/app/views/shared/_labels_row.html.haml
@@ -1,10 +1,9 @@
- labels.each do |label|
- %span.label-row.btn-group{ role: "group", aria: { label: escape_once(label.name) }, style: "color: #{text_color_for_bg(label.color)}" }
- = link_to label_filter_path(@project, label, type: controller.controller_name),
+ %span.label-row.btn-group{ role: "group", aria: { label: label.name }, style: "color: #{text_color_for_bg(label.color)}" }
+ = link_to label.name, label_filter_path(@project, label, type: controller.controller_name),
class: "btn btn-transparent has-tooltip",
style: "background-color: #{label.color};",
title: escape_once(label.description),
- data: { container: "body" } do
- = escape_once label.name
+ data: { container: "body" }
%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/_visibility_level.html.haml b/app/views/shared/_visibility_level.html.haml
index 1c6ec198d3d..107ad19177c 100644
--- a/app/views/shared/_visibility_level.html.haml
+++ b/app/views/shared/_visibility_level.html.haml
@@ -1,7 +1,7 @@
.form-group.project-visibility-level-holder
= f.label :visibility_level, class: 'control-label' do
Visibility Level
- = link_to "(?)", help_page_path("public_access", "public_access")
+ = link_to "(?)", help_page_path("public_access/public_access")
.col-sm-10
- if can_change_visibility_level
= render('shared/visibility_radios', model_method: :visibility_level, form: f, selected_level: visibility_level, form_model: form_model)
diff --git a/app/views/shared/icons/_issues.svg b/app/views/shared/icons/_issues.svg
deleted file mode 100644
index 2682c27ade9..00000000000
--- a/app/views/shared/icons/_issues.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg width="16px" height="16px" viewBox="0 0 16 16" 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="M8,0 C3.581,0 0,3.581 0,8 C0,12.419 3.581,16 8,16 C12.419,16 16,12.419 16,8 C16,3.581 12.419,0 8,0 M8,2 C11.308,2 14,4.692 14,8 C14,11.308 11.308,14 8,14 C4.692,14 2,11.308 2,8 C2,4.692 4.692,2 8,2" id="Fill-1"></path>
- <path d="M7.1597,4 L8.8887,4 L8.8887,8 L7.1107,8 L7.1597,4 Z M7.1597,9.6667 L8.8887,9.6667 L8.8887,11.4447 L7.1107,11.4447 L7.1597,9.6667 Z" id="Combined-Shape"></path>
- </g>
- </g>
-</svg> \ No newline at end of file
diff --git a/app/views/shared/icons/_issues.svg.erb b/app/views/shared/icons/_issues.svg.erb
new file mode 100644
index 00000000000..fa8655b5609
--- /dev/null
+++ b/app/views/shared/icons/_issues.svg.erb
@@ -0,0 +1,4 @@
+<svg width="<%= size %>" height="<%= size %>" viewBox="0 0 16 16" class="gitlab-icon">
+ <path fill="#7E7C7C" d="M8,0 C3.581,0 0,3.581 0,8 C0,12.419 3.581,16 8,16 C12.419,16 16,12.419 16,8 C16,3.581 12.419,0 8,0 M8,2 C11.308,2 14,4.692 14,8 C14,11.308 11.308,14 8,14 C4.692,14 2,11.308 2,8 C2,4.692 4.692,2 8,2"></path>
+ <path fill="#7E7C7C" d="M7.1597,4 L8.8887,4 L8.8887,8 L7.1107,8 L7.1597,4 Z M7.1597,9.6667 L8.8887,9.6667 L8.8887,11.4447 L7.1107,11.4447 L7.1597,9.6667 Z"></path>
+</svg>
diff --git a/app/views/shared/members/_access_request_buttons.html.haml b/app/views/shared/members/_access_request_buttons.html.haml
index 35dcdccc921..eff914398bb 100644
--- a/app/views/shared/members/_access_request_buttons.html.haml
+++ b/app/views/shared/members/_access_request_buttons.html.haml
@@ -1,4 +1,4 @@
-- if can_see_request_access_button?(source)
+- if can?(current_user, :request_access, source)
- if requester = source.requesters.find_by(user_id: current_user.id)
= link_to 'Withdraw Access Request', polymorphic_path([:leave, source, :members]),
method: :delete,
diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml
index a884e78e6e7..5ae485f36ba 100644
--- a/app/views/shared/members/_member.html.haml
+++ b/app/views/shared/members/_member.html.haml
@@ -3,71 +3,74 @@
- user = member.user
%li.js-toggle-container{ class: dom_class(member), id: dom_id(member) }
- %span{ class: ("list-item-name" if show_controls) }
- - if user
- = image_tag avatar_icon(user, 24), class: "avatar s24", alt: ''
- %strong
- = link_to user.name, user_path(user)
- %span.cgray= user.username
-
- - if user == current_user
- %span.label.label-success It's you
-
- - if user.blocked?
- %label.label.label-danger
- %strong Blocked
-
- - if member.request?
- %span.cgray
- – Requested
- = time_ago_with_tooltip(member.requested_at)
- - else
- = image_tag avatar_icon(member.invite_email, 24), class: "avatar s24", alt: ''
- %strong= member.invite_email
- %span.cgray
- – Invited
- - if member.created_by
- by
- = link_to member.created_by.name, user_path(member.created_by)
- = time_ago_with_tooltip(member.created_at)
-
- - if show_controls && can?(current_user, action_member_permission(:admin, member), member.source)
- = link_to 'Resend invite', polymorphic_path([:resend_invite, member]),
- method: :post,
- class: 'btn-xs btn'
-
- if show_roles
- %span.pull-right
- %strong= member.human_access
+ .controls
+ %strong.control-text= member.human_access
- if show_controls
+ - if !user && can?(current_user, action_member_permission(:admin, member), member.source)
+ = link_to 'Resend invite', polymorphic_path([:resend_invite, member]),
+ method: :post,
+ class: 'btn'
+
- if can?(current_user, action_member_permission(:update, member), member)
= button_tag icon('pencil'),
type: 'button',
- class: 'btn-xs btn btn-grouped inline js-toggle-button',
+ class: 'btn inline js-toggle-button',
title: 'Edit access level'
- if member.request?
- &nbsp;
= link_to icon('check inverse'), polymorphic_path([:approve_access_request, member]),
method: :post,
- class: 'btn-xs btn btn-success',
+ class: 'btn btn-success',
title: 'Grant access'
- if can?(current_user, action_member_permission(:destroy, member), member)
- &nbsp;
- if current_user == user
= link_to icon('sign-out', text: 'Leave'), polymorphic_path([:leave, member.source, :members]),
method: :delete,
data: { confirm: leave_confirmation_message(member.source) },
- class: 'btn-xs btn btn-remove'
+ class: 'btn btn-remove'
- else
= link_to icon('trash'), member,
remote: true,
method: :delete,
data: { confirm: remove_member_message(member) },
- class: 'btn-xs btn btn-remove',
+ class: 'btn btn-remove',
title: remove_member_title(member)
+
+ %span{ class: ("list-item-name" if show_controls) }
+ - if user
+ = image_tag avatar_icon(user, 40), class: "avatar s40", alt: ''
+ %strong
+ = link_to user.name, user_path(user)
+ %span.cgray= user.username
+
+ - if user == current_user
+ %span.label.label-success It's you
+
+ - if user.blocked?
+ %label.label.label-danger
+ %strong Blocked
+
+ .cgray
+ - if member.request?
+ Requested
+ = time_ago_with_tooltip(member.requested_at)
+ - else
+ Joined #{time_ago_with_tooltip(member.created_at)}
+
+ - else
+ = image_tag avatar_icon(member.invite_email, 40), class: "avatar s40", alt: ''
+ %strong= member.invite_email
+ .cgray
+ Invited
+ - if member.created_by
+ by
+ = link_to member.created_by.name, user_path(member.created_by)
+ = time_ago_with_tooltip(member.created_at)
+
+ - if show_roles
.edit-member.hide.js-toggle-content
%br
= form_for member, remote: true do |f|
diff --git a/app/views/shared/milestones/_summary.html.haml b/app/views/shared/milestones/_summary.html.haml
index 975c74f4ea6..dee2472fa79 100644
--- a/app/views/shared/milestones/_summary.html.haml
+++ b/app/views/shared/milestones/_summary.html.haml
@@ -26,7 +26,6 @@
%span.pull-right.tab-issues-buttons
- if project && can?(current_user, :create_issue, project)
= link_to new_namespace_project_issue_path(project.namespace, project, issue: { milestone_id: milestone.id }), class: "btn btn-grouped", title: "New Issue" do
- %i.fa.fa-plus
New Issue
= link_to 'Browse Issues', milestones_browse_issuables_path(milestone, type: :issues), class: "btn btn-grouped"
%span.pull-right.tab-merge-requests-buttons.hidden
diff --git a/app/views/shared/projects/_dropdown.html.haml b/app/views/shared/projects/_dropdown.html.haml
index 1169bed0382..b7f8551153b 100644
--- a/app/views/shared/projects/_dropdown.html.haml
+++ b/app/views/shared/projects/_dropdown.html.haml
@@ -1,31 +1,30 @@
- @sort ||= sort_value_recently_updated
- personal = params[:personal]
- archived = params[:archived]
+- namespace_id = params[:namespace_id]
.dropdown.inline
- %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'}
- %span.light
- = projects_sort_options_hash[@sort]
- %b.caret
+ - toggle_text = projects_sort_options_hash[@sort]
+ = dropdown_toggle(toggle_text, { toggle: 'dropdown' }, { id: 'sort-projects-dropdown' })
%ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-selectable
%li.dropdown-header
Sort by
- projects_sort_options_hash.each do |value, title|
%li
- = link_to filter_projects_path(sort: value, archived: archived, personal: personal), class: ("is-active" if @sort == value) do
+ = link_to filter_projects_path(namespace_id: namespace_id, sort: value, archived: archived, personal: personal), class: ("is-active" if @sort == value) do
= title
%li.divider
%li
- = link_to filter_projects_path(sort: @sort, archived: nil), class: ("is-active" unless params[:archived].present?) do
+ = link_to filter_projects_path(namespace_id: namespace_id, sort: @sort, archived: nil), class: ("is-active" unless params[:archived].present?) do
Hide archived projects
%li
- = link_to filter_projects_path(sort: @sort, archived: true), class: ("is-active" if params[:archived].present?) do
+ = link_to filter_projects_path(namespace_id: namespace_id, sort: @sort, archived: true), class: ("is-active" if params[:archived].present?) do
Show archived projects
- if current_user
%li.divider
%li
- = link_to filter_projects_path(sort: @sort, personal: nil), class: ("is-active" unless personal) do
+ = link_to filter_projects_path(namespace_id: namespace_id, sort: @sort, personal: nil), class: ("is-active" unless personal.present?) do
Owned by anyone
%li
- = link_to filter_projects_path(sort: @sort, personal: true), class: ("is-active" if personal) do
+ = link_to filter_projects_path(namespace_id: namespace_id, sort: @sort, personal: true), class: ("is-active" if personal.present?) do
Owned by me
diff --git a/app/views/shared/web_hooks/_form.html.haml b/app/views/shared/web_hooks/_form.html.haml
index d1e861ca80c..2585ed9360b 100644
--- a/app/views/shared/web_hooks/_form.html.haml
+++ b/app/views/shared/web_hooks/_form.html.haml
@@ -6,7 +6,7 @@
%h4.prepend-top-0
= page_title
%p
- #{link_to "Webhooks", help_page_path("web_hooks", "web_hooks")} can be
+ #{link_to "Webhooks", help_page_path("web_hooks/web_hooks")} can be
used for binding events when something is happening within the project.
.col-lg-9.append-bottom-default
= form_for hook, as: :hook, url: polymorphic_path(url_components + [:hooks]) do |f|
diff --git a/app/views/snippets/_actions.html.haml b/app/views/snippets/_actions.html.haml
index a7769654b61..160c6cd84da 100644
--- a/app/views/snippets/_actions.html.haml
+++ b/app/views/snippets/_actions.html.haml
@@ -1,27 +1,28 @@
.hidden-xs
- = link_to new_snippet_path, class: "btn btn-grouped btn-create new-snippet-link", title: "New Snippet" do
- = icon('plus')
- New Snippet
+ - if current_user
+ = link_to new_snippet_path, class: "btn btn-grouped btn-create new-snippet-link", title: "New Snippet" do
+ New Snippet
- if can?(current_user, :update_personal_snippet, @snippet)
= link_to edit_snippet_path(@snippet), class: "btn btn-grouped snippable-edit" do
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-warning", title: 'Delete Snippet' do
+ = link_to snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-danger", title: 'Delete Snippet' do
Delete
-.visible-xs-block.dropdown
- %button.btn.btn-default.btn-block.append-bottom-0.prepend-top-5{ data: { toggle: "dropdown" } }
- Options
- %span.caret
- .dropdown-menu.dropdown-menu-full-width
- %ul
- %li
- = link_to new_snippet_path, title: "New Snippet" do
- New Snippet
- - if can?(current_user, :update_personal_snippet, @snippet)
+- if current_user
+ .visible-xs-block.dropdown
+ %button.btn.btn-default.btn-block.append-bottom-0.prepend-top-5{ data: { toggle: "dropdown" } }
+ Options
+ %span.caret
+ .dropdown-menu.dropdown-menu-full-width
+ %ul
%li
- = link_to edit_snippet_path(@snippet) do
- Edit
- - 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 new_snippet_path, title: "New Snippet" do
+ New Snippet
+ - if can?(current_user, :update_personal_snippet, @snippet)
+ %li
+ = link_to edit_snippet_path(@snippet) do
+ Edit
+ - 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
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 68665858c3e..db2b4885861 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -29,6 +29,11 @@
&nbsp;
= link_to user_path(@user, :atom, { private_token: current_user.private_token }), class: 'btn btn-gray' do
= icon('rss')
+ - if current_user.admin?
+ &nbsp;
+ = link_to [:admin, @user], class: 'btn btn-gray', title: 'View user in admin area',
+ data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = icon('users')
.avatar-holder
= link_to avatar_icon(@user, 400), target: '_blank' do
diff --git a/app/workers/emails_on_push_worker.rb b/app/workers/emails_on_push_worker.rb
index 971f969e25e..8551288e2f2 100644
--- a/app/workers/emails_on_push_worker.rb
+++ b/app/workers/emails_on_push_worker.rb
@@ -28,18 +28,30 @@ class EmailsOnPushWorker
:push
end
+ merge_base_sha = project.merge_base_commit(before_sha, after_sha).try(:sha)
+
diff_refs = nil
compare = nil
reverse_compare = false
if action == :push
compare = Gitlab::Git::Compare.new(project.repository.raw_repository, before_sha, after_sha)
- diff_refs = [project.merge_base_commit(before_sha, after_sha), project.commit(after_sha)]
+
+ diff_refs = Gitlab::Diff::DiffRefs.new(
+ base_sha: merge_base_sha,
+ start_sha: before_sha,
+ head_sha: after_sha
+ )
return false if compare.same
if compare.commits.empty?
compare = Gitlab::Git::Compare.new(project.repository.raw_repository, after_sha, before_sha)
- diff_refs = [project.merge_base_commit(after_sha, before_sha), project.commit(before_sha)]
+
+ diff_refs = Gitlab::Diff::DiffRefs.new(
+ base_sha: merge_base_sha,
+ start_sha: after_sha,
+ head_sha: before_sha
+ )
reverse_compare = true
diff --git a/app/workers/git_garbage_collect_worker.rb b/app/workers/git_garbage_collect_worker.rb
new file mode 100644
index 00000000000..2fa3c838f55
--- /dev/null
+++ b/app/workers/git_garbage_collect_worker.rb
@@ -0,0 +1,14 @@
+class GitGarbageCollectWorker
+ include Sidekiq::Worker
+ include Gitlab::ShellAdapter
+
+ sidekiq_options queue: :gitlab_shell, retry: false
+
+ def perform(project_id)
+ project = Project.find(project_id)
+
+ gitlab_shell.gc(project.repository_storage_path, project.path_with_namespace)
+ # Expire the branch cache in case garbage collection caused a ref lookup to fail
+ project.repository.after_create_branch
+ end
+end
diff --git a/app/workers/gitlab_shell_one_shot_worker.rb b/app/workers/gitlab_shell_one_shot_worker.rb
deleted file mode 100644
index 4ddbcf574d5..00000000000
--- a/app/workers/gitlab_shell_one_shot_worker.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-class GitlabShellOneShotWorker
- include Sidekiq::Worker
- include Gitlab::ShellAdapter
-
- sidekiq_options queue: :gitlab_shell, retry: false
-
- def perform(action, *arg)
- gitlab_shell.send(action, *arg)
- end
-end
diff --git a/config/application.rb b/config/application.rb
index 2b0595ede2b..21e7cc7b6e8 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -84,6 +84,7 @@ module Gitlab
config.assets.precompile << "graphs/application.js"
config.assets.precompile << "users/application.js"
config.assets.precompile << "network/application.js"
+ config.assets.precompile << "profile/application.js"
config.assets.precompile << "lib/utils/*.js"
config.assets.precompile << "lib/*.js"
diff --git a/config/initializers/health_check.rb b/config/initializers/health_check.rb
index 6796407d4e6..4c91a61fb4a 100644
--- a/config/initializers/health_check.rb
+++ b/config/initializers/health_check.rb
@@ -1,16 +1,3 @@
-# Email forcibly included in the standard checks, but the email health check
-# doesn't support the full range of SMTP options, which can result in failures
-# for valid SMTP configurations.
-# Overwrite the HealthCheck's detection of whether email is configured
-# in order to avoid the email check during standard checks
-module HealthCheck
- class Utils
- def self.mailer_configured?
- false
- end
- end
-end
-
HealthCheck.setup do |config|
config.standard_checks = ['database', 'migrations', 'cache']
config.full_checks = ['database', 'migrations', 'cache']
diff --git a/config/initializers/metrics.rb b/config/initializers/metrics.rb
index 44601f2b2bd..c4266ab8ba5 100644
--- a/config/initializers/metrics.rb
+++ b/config/initializers/metrics.rb
@@ -135,6 +135,8 @@ if Gitlab::Metrics.enabled?
config.instrument_instance_methods(Rouge::Plugins::Redcarpet)
config.instrument_instance_methods(Rouge::Formatters::HTMLGitlab)
+
+ config.instrument_methods(Rinku)
end
GC::Profiler.enable
diff --git a/config/routes.rb b/config/routes.rb
index 1572656b8c5..3160fd767b8 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -89,8 +89,9 @@ Rails.application.routes.draw do
mount Grack::AuthSpawner, at: '/', constraints: lambda { |request| /[-\/\w\.]+\.git\/(info\/lfs|gitlab-lfs)/.match(request.path_info) }, via: [:get, :post, :put]
# Help
+
get 'help' => 'help#index'
- get 'help/:category/:file' => 'help#show', as: :help_page, constraints: { category: /.*/, file: /[^\/\.]+/ }
+ get 'help/*path' => 'help#show', as: :help_page
get 'help/shortcuts'
get 'help/ui' => 'help#ui'
@@ -615,10 +616,18 @@ Rails.application.routes.draw do
post :retry_builds
post :revert
post :cherry_pick
+ get :diff_for_path
end
end
- resources :compare, only: [:index, :create]
+ resources :compare, only: [:index, :create] do
+ collection do
+ get :diff_for_path
+ end
+ end
+
+ get '/compare/:from...:to', to: 'compare#show', as: 'compare', constraints: { from: /.+/, to: /.+/ }
+
resources :network, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ }
resources :graphs, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ } do
@@ -629,9 +638,6 @@ Rails.application.routes.draw do
end
end
- get '/compare/:from...:to' => 'compare#show', :as => 'compare',
- :constraints => { from: /.+/, to: /.+/ }
-
resources :snippets, constraints: { id: /\d+/ } do
member do
get 'raw'
@@ -706,12 +712,14 @@ Rails.application.routes.draw do
post :toggle_subscription
post :toggle_award_emoji
post :remove_wip
+ get :diff_for_path
end
collection do
get :branch_from
get :branch_to
get :update_branches
+ get :diff_for_path
end
end
@@ -720,7 +728,7 @@ Rails.application.routes.draw do
resource :release, only: [:edit, :update]
end
- resources :protected_branches, only: [:index, :create, :update, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex }
+ resources :protected_branches, only: [:index, :show, :create, :update, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex }
resources :variables, only: [:index, :show, :update, :create, :destroy]
resources :triggers, only: [:index, :create, :destroy]
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
new file mode 100644
index 00000000000..1c4d60e7234
--- /dev/null
+++ b/db/migrate/20160508202603_add_head_commit_id_to_merge_request_diffs.rb
@@ -0,0 +1,5 @@
+class AddHeadCommitIdToMergeRequestDiffs < ActiveRecord::Migration
+ def change
+ add_column :merge_request_diffs, :head_commit_sha, :string
+ end
+end
diff --git a/db/migrate/20160508215920_add_positions_to_diff_notes.rb b/db/migrate/20160508215920_add_positions_to_diff_notes.rb
new file mode 100644
index 00000000000..2952c25004e
--- /dev/null
+++ b/db/migrate/20160508215920_add_positions_to_diff_notes.rb
@@ -0,0 +1,6 @@
+class AddPositionsToDiffNotes < ActiveRecord::Migration
+ def change
+ add_column :notes, :position, :text
+ add_column :notes, :original_position, :text
+ end
+end
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
new file mode 100644
index 00000000000..b7fd76ee84b
--- /dev/null
+++ b/db/migrate/20160516224534_add_start_commit_id_to_merge_request_diffs.rb
@@ -0,0 +1,5 @@
+class AddStartCommitIdToMergeRequestDiffs < ActiveRecord::Migration
+ def change
+ add_column :merge_request_diffs, :start_commit_sha, :string
+ end
+end
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
new file mode 100644
index 00000000000..4eef16c9408
--- /dev/null
+++ b/db/migrate/20160522215720_add_note_type_and_position_to_sent_notification.rb
@@ -0,0 +1,22 @@
+# 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
+ include Gitlab::Database::MigrationHelpers
+
+ # When using the methods "add_concurrent_index" or "add_column_with_default"
+ # you must disable the use of transactions as these methods can not run in an
+ # existing transaction. When using "add_concurrent_index" make sure that this
+ # method is the _only_ method called in the migration, any other changes
+ # should go in a separate migration. This ensures that upon failure _only_ the
+ # index creation fails and can be retried or reverted easily.
+ #
+ # To disable transactions uncomment the following line and remove these
+ # comments:
+ # disable_ddl_transaction!
+
+ def change
+ add_column :sent_notifications, :note_type, :string
+ add_column :sent_notifications, :position, :text
+ end
+end
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
new file mode 100644
index 00000000000..34c702e3fa6
--- /dev/null
+++ b/db/migrate/20160608211215_add_user_default_external_to_application_settings.rb
@@ -0,0 +1,13 @@
+class AddUserDefaultExternalToApplicationSettings < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default(:application_settings, :user_default_external, :boolean,
+ default: false, allow_null: false)
+ end
+
+ def down
+ remove_column(:application_settings, :user_default_external)
+ end
+end
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
new file mode 100644
index 00000000000..013904b3f4f
--- /dev/null
+++ b/db/migrate/20160615173316_add_enabled_git_access_protocols_to_application_settings.rb
@@ -0,0 +1,11 @@
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+# rubocop:disable all
+
+class AddEnabledGitAccessProtocolsToApplicationSettings < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ def change
+ add_column :application_settings, :enabled_git_access_protocol, :string
+ end
+end
diff --git a/db/migrate/20160616102642_remove_duplicated_keys.rb b/db/migrate/20160616102642_remove_duplicated_keys.rb
index 00a45d7fe73..180a75e0998 100644
--- a/db/migrate/20160616102642_remove_duplicated_keys.rb
+++ b/db/migrate/20160616102642_remove_duplicated_keys.rb
@@ -4,12 +4,12 @@ class RemoveDuplicatedKeys < ActiveRecord::Migration
select_all("SELECT fingerprint FROM #{quote_table_name(:keys)} GROUP BY fingerprint HAVING COUNT(*) > 1").each do |row|
fingerprint = connection.quote(row['fingerprint'])
execute(%Q{
- DELETE FROM keys
+ DELETE FROM #{quote_table_name(:keys)}
WHERE fingerprint = #{fingerprint}
AND id != (
SELECT id FROM (
SELECT max(id) AS id
- FROM keys
+ FROM #{quote_table_name(:keys)}
WHERE fingerprint = #{fingerprint}
) max_ids
)
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
new file mode 100644
index 00000000000..0c25f87dfb4
--- /dev/null
+++ b/db/migrate/20160703180340_add_index_on_award_emoji_user_and_name.rb
@@ -0,0 +1,11 @@
+# rubocop:disable all
+# Migration type: online without errors
+
+class AddIndexOnAwardEmojiUserAndName < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+ disable_ddl_transaction!
+
+ def change
+ add_concurrent_index(:award_emoji, [:user_id, :name])
+ end
+end
diff --git a/db/migrate/20160705163108_remove_requesters_that_are_owners.rb b/db/migrate/20160705163108_remove_requesters_that_are_owners.rb
new file mode 100644
index 00000000000..1fca230c019
--- /dev/null
+++ b/db/migrate/20160705163108_remove_requesters_that_are_owners.rb
@@ -0,0 +1,40 @@
+class RemoveRequestersThatAreOwners < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ def up
+ # Delete requesters that are owner of their projects and actually requested
+ # access to it
+ execute <<-SQL
+ DELETE FROM members
+ WHERE members.source_type = 'Project'
+ AND members.type = 'ProjectMember'
+ AND members.requested_at IS NOT NULL
+ AND members.user_id = (
+ SELECT namespaces.owner_id
+ FROM namespaces
+ JOIN projects ON namespaces.id = projects.namespace_id
+ WHERE namespaces.type IS NULL
+ AND projects.id = members.source_id
+ AND namespaces.owner_id = members.user_id);
+ SQL
+
+ # Delete requesters that are owner of their project's group and actually requested
+ # access to it
+ execute <<-SQL
+ DELETE FROM members
+ WHERE members.source_type = 'Project'
+ AND members.type = 'ProjectMember'
+ AND members.requested_at IS NOT NULL
+ AND members.user_id = (
+ SELECT namespaces.owner_id
+ FROM namespaces
+ JOIN projects ON namespaces.id = projects.namespace_id
+ WHERE namespaces.type = 'Group'
+ AND projects.id = members.source_id
+ AND namespaces.owner_id = members.user_id);
+ SQL
+ end
+
+ def down
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 0f5f9f243fa..a5eea3a697c 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20160628085157) do
+ActiveRecord::Schema.define(version: 20160705163108) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -84,8 +84,10 @@ ActiveRecord::Schema.define(version: 20160628085157) do
t.string "health_check_access_token"
t.boolean "send_user_confirmation_email", default: false
t.integer "container_registry_token_expire_delay", default: 5
+ t.boolean "user_default_external", default: false, null: false
t.text "after_sign_up_text"
t.string "repository_storage", default: "default"
+ t.string "enabled_git_access_protocol"
end
create_table "audit_events", force: :cascade do |t|
@@ -112,6 +114,7 @@ ActiveRecord::Schema.define(version: 20160628085157) do
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
add_index "award_emoji", ["user_id"], name: "index_award_emoji_on_user_id", using: :btree
create_table "broadcast_messages", force: :cascade do |t|
@@ -591,6 +594,8 @@ ActiveRecord::Schema.define(version: 20160628085157) do
t.datetime "updated_at"
t.string "base_commit_sha"
t.string "real_size"
+ t.string "head_commit_sha"
+ t.string "start_commit_sha"
end
add_index "merge_request_diffs", ["merge_request_id"], name: "index_merge_request_diffs_on_merge_request_id", unique: true, using: :btree
@@ -687,10 +692,12 @@ ActiveRecord::Schema.define(version: 20160628085157) do
t.string "line_code"
t.string "commit_id"
t.integer "noteable_id"
- t.boolean "system", default: false, null: false
+ t.boolean "system", default: false, null: false
t.text "st_diff"
t.integer "updated_by_id"
t.string "type"
+ t.text "position"
+ t.text "original_position"
end
add_index "notes", ["author_id"], name: "index_notes_on_author_id", using: :btree
@@ -879,6 +886,8 @@ ActiveRecord::Schema.define(version: 20160628085157) do
t.string "commit_id"
t.string "reply_key", null: false
t.string "line_code"
+ t.string "note_type"
+ t.text "position"
end
add_index "sent_notifications", ["reply_key"], name: "index_sent_notifications_on_reply_key", unique: true, using: :btree
diff --git a/doc/README.md b/doc/README.md
index b98d6812a81..cf7a828d91e 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -21,9 +21,10 @@
## Administrator documentation
+- [Access restrictions](administration/access_restrictions.md) Define which Git access protocols can be used to talk to GitLab
- [Authentication/Authorization](administration/auth/README.md) Configure
external authentication with LDAP, SAML, CAS and additional Omniauth providers.
-- [Custom git hooks](hooks/custom_hooks.md) Custom git hooks (on the filesystem) for when webhooks aren't enough.
+- [Custom Git hooks](administration/custom_hooks.md) Custom Git hooks (on the filesystem) for when webhooks aren't enough.
- [Install](install/README.md) Requirements, directory structures and installation from source.
- [Restart GitLab](administration/restart_gitlab.md) Learn how to restart GitLab and its components.
- [Integration](integration/README.md) How to integrate with systems such as JIRA, Redmine, Twitter.
diff --git a/doc/administration/access_restrictions.md b/doc/administration/access_restrictions.md
new file mode 100644
index 00000000000..51d7996effd
--- /dev/null
+++ b/doc/administration/access_restrictions.md
@@ -0,0 +1,38 @@
+# Access Restrictions
+
+> **Note:** This feature is only available on versions 8.10 and above.
+
+With GitLab's Access restrictions you can choose which Git access protocols you
+want your users to use to communicate with GitLab. This feature can be enabled
+via the `Application Settings` in the Admin interface.
+
+The setting is called `Enabled Git access protocols`, and it gives you the option
+to choose between:
+
+- Both SSH and HTTP(S)
+- Only SSH
+- Only HTTP(s)
+
+![Settings Overview](img/access_restrictions.png)
+
+## Enabled Protocol
+
+When both SSH and HTTP(S) are enabled, GitLab will behave as usual, it will give
+your users the option to choose which protocol they would like to use.
+
+When you choose to allow only one of the protocols, a couple of things will happen:
+
+- The project page will only show the allowed protocol's URL, with no option to
+ change it.
+- A tooltip will be shown when you hover over the URL's protocol, if an action
+ on the user's part is required, e.g. adding an SSH key, or setting a password.
+
+![Project URL with SSH only access](img/restricted_url.png)
+
+On top of these UI restrictions, GitLab will deny all Git actions on the protocol
+not selected.
+
+> **Note:** Please keep in mind that disabling an access protocol does not actually
+ block access to the server itself. The ports used for the protocol, be it SSH or
+ HTTP, will still be accessible. What GitLab does is restrict access on the
+ application level. \ No newline at end of file
diff --git a/doc/administration/auth/ldap.md b/doc/administration/auth/ldap.md
index 10096779844..7186f707ad6 100644
--- a/doc/administration/auth/ldap.md
+++ b/doc/administration/auth/ldap.md
@@ -130,27 +130,27 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server
first_name: 'givenName'
last_name: 'sn'
- ## EE only
-
- # Base where we can search for groups
- #
- # Ex. ou=groups,dc=gitlab,dc=example
- #
- group_base: ''
-
- # The CN of a group containing GitLab administrators
- #
- # Ex. administrators
- #
- # Note: Not `cn=administrators` or the full DN
- #
- admin_group: ''
-
- # The LDAP attribute containing a user's public SSH key
- #
- # Ex. ssh_public_key
- #
- sync_ssh_keys: false
+ ## EE only
+
+ # Base where we can search for groups
+ #
+ # Ex. ou=groups,dc=gitlab,dc=example
+ #
+ group_base: ''
+
+ # The CN of a group containing GitLab administrators
+ #
+ # Ex. administrators
+ #
+ # Note: Not `cn=administrators` or the full DN
+ #
+ admin_group: ''
+
+ # The LDAP attribute containing a user's public SSH key
+ #
+ # Ex. ssh_public_key
+ #
+ sync_ssh_keys: false
# GitLab EE only: add more LDAP servers
# Choose an ID made of a-z and 0-9 . This ID will be stored in the database
diff --git a/doc/administration/custom_hooks.md b/doc/administration/custom_hooks.md
new file mode 100644
index 00000000000..e3306c22d3f
--- /dev/null
+++ b/doc/administration/custom_hooks.md
@@ -0,0 +1,57 @@
+# Custom Git Hooks
+
+>
+**Note:** Custom Git hooks must be configured on the filesystem of the GitLab
+server. Only GitLab server administrators will be able to complete these tasks.
+Please explore [webhooks](../web_hooks/web_hooks.md) as an option if you do not
+have filesystem access. For a user configurable Git hook interface, please see
+[GitLab Enterprise Edition Git Hooks](http://docs.gitlab.com/ee/git_hooks/git_hooks.html).
+
+Git natively supports hooks that are executed on different actions.
+Examples of server-side git hooks include pre-receive, post-receive, and update.
+See [Git SCM Server-Side Hooks][hooks] for more information about each hook type.
+
+As of gitlab-shell version 2.2.0 (which requires GitLab 7.5+), GitLab
+administrators can add custom git hooks to any GitLab project.
+
+## Setup
+
+Normally, Git hooks are placed in the repository or project's `hooks` directory.
+GitLab creates a symlink from each project's `hooks` directory to the
+gitlab-shell `hooks` directory for ease of maintenance between gitlab-shell
+upgrades. As such, custom hooks are implemented a little differently. Behavior
+is exactly the same once the hook is created, though.
+
+Follow the steps below to set up a custom hook:
+
+1. Pick a project that needs a custom Git hook.
+1. On the GitLab server, navigate to the project's repository directory.
+ For an installation from source the path is usually
+ `/home/git/repositories/<group>/<project>.git`. For Omnibus installs the path is
+ usually `/var/opt/gitlab/git-data/repositories/<group>/<project>.git`.
+1. Create a new directory in this location called `custom_hooks`.
+1. Inside the new `custom_hooks` directory, create a file with a name matching
+ the hook type. For a pre-receive hook the file name should be `pre-receive`
+ with no extension.
+1. Make the hook file executable and make sure it's owned by git.
+1. Write the code to make the Git hook function as expected. Hooks can be
+ in any language. Ensure the 'shebang' at the top properly reflects the language
+ type. For example, if the script is in Ruby the shebang will probably be
+ `#!/usr/bin/env ruby`.
+
+That's it! Assuming the hook code is properly implemented the hook will fire
+as appropriate.
+
+## Custom error messages
+
+>**Note:**
+This feature was [introduced][5073] in GitLab 8.10.
+
+If the commit is declined or an error occurs during the Git hook check,
+the STDERR or STDOUT message of the hook will be present in GitLab's UI.
+STDERR takes precedence over STDOUT.
+
+![Custom message from custom Git hook](img/custom_hooks_error_msg.png)
+
+[hooks]: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#Server-Side-Hooks
+[5073]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5073
diff --git a/doc/administration/img/access_restrictions.png b/doc/administration/img/access_restrictions.png
new file mode 100644
index 00000000000..66fd9491e85
--- /dev/null
+++ b/doc/administration/img/access_restrictions.png
Binary files differ
diff --git a/doc/administration/img/custom_hooks_error_msg.png b/doc/administration/img/custom_hooks_error_msg.png
new file mode 100644
index 00000000000..92e87e15fb3
--- /dev/null
+++ b/doc/administration/img/custom_hooks_error_msg.png
Binary files differ
diff --git a/doc/administration/img/restricted_url.png b/doc/administration/img/restricted_url.png
new file mode 100644
index 00000000000..0a677433dcf
--- /dev/null
+++ b/doc/administration/img/restricted_url.png
Binary files differ
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 1ccb9715e96..87480bebfc4 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -42,46 +42,49 @@ Parameters:
```json
[
{
- "id": 4,
- "description": null,
+ "id": 9,
+ "description": "foo",
"default_branch": "master",
+ "tag_list": [],
"public": false,
- "visibility_level": 0,
- "ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git",
- "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git",
- "web_url": "http://example.com/diaspora/diaspora-client",
- "tag_list": [
- "example",
- "disapora client"
- ],
- "owner": {
- "id": 3,
- "name": "Diaspora",
- "created_at": "2013-09-30T13: 46: 02Z"
- },
- "name": "Diaspora Client",
- "name_with_namespace": "Diaspora / Diaspora Client",
- "path": "diaspora-client",
- "path_with_namespace": "diaspora/diaspora-client",
+ "archived": false,
+ "visibility_level": 10,
+ "ssh_url_to_repo": "git@gitlab.example.com/html5-boilerplate.git",
+ "http_url_to_repo": "http://gitlab.example.com/h5bp/html5-boilerplate.git",
+ "web_url": "http://gitlab.example.com/h5bp/html5-boilerplate",
+ "name": "Html5 Boilerplate",
+ "name_with_namespace": "Experimental / Html5 Boilerplate",
+ "path": "html5-boilerplate",
+ "path_with_namespace": "h5bp/html5-boilerplate",
"issues_enabled": true,
"merge_requests_enabled": true,
- "builds_enabled": true,
"wiki_enabled": true,
- "snippets_enabled": false,
- "created_at": "2013-09-30T13: 46: 02Z",
- "last_activity_at": "2013-09-30T13: 46: 02Z",
- "creator_id": 3,
+ "builds_enabled": true,
+ "snippets_enabled": true,
+ "created_at": "2016-04-05T21:40:50.169Z",
+ "last_activity_at": "2016-04-06T16:52:08.432Z",
+ "shared_runners_enabled": true,
+ "creator_id": 1,
"namespace": {
- "created_at": "2013-09-30T13: 46: 02Z",
- "description": "",
- "id": 3,
- "name": "Diaspora",
- "owner_id": 1,
- "path": "diaspora",
- "updated_at": "2013-09-30T13: 46: 02Z"
+ "id": 5,
+ "name": "Experimental",
+ "path": "h5bp",
+ "owner_id": null,
+ "created_at": "2016-04-05T21:40:49.152Z",
+ "updated_at": "2016-04-07T08:07:48.466Z",
+ "description": "foo",
+ "avatar": {
+ "url": null
+ },
+ "share_with_group_lock": false,
+ "visibility_level": 10
},
- "archived": false,
- "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png"
+ "avatar_url": null,
+ "star_count": 1,
+ "forks_count": 0,
+ "open_issues_count": 3,
+ "public_builds": true,
+ "shared_with_groups": []
}
]
```
@@ -96,7 +99,180 @@ GET /groups/:id
Parameters:
-- `id` (required) - The ID or path of a group
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or path of a group |
+
+```bash
+curl -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/4
+```
+
+Example response:
+
+```json
+{
+ "id": 4,
+ "name": "Twitter",
+ "path": "twitter",
+ "description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.",
+ "visibility_level": 20,
+ "avatar_url": null,
+ "web_url": "https://gitlab.example.com/groups/twitter",
+ "projects": [
+ {
+ "id": 7,
+ "description": "Voluptas veniam qui et beatae voluptas doloremque explicabo facilis.",
+ "default_branch": "master",
+ "tag_list": [],
+ "public": true,
+ "archived": false,
+ "visibility_level": 20,
+ "ssh_url_to_repo": "git@gitlab.example.com:twitter/typeahead-js.git",
+ "http_url_to_repo": "https://gitlab.example.com/twitter/typeahead-js.git",
+ "web_url": "https://gitlab.example.com/twitter/typeahead-js",
+ "name": "Typeahead.Js",
+ "name_with_namespace": "Twitter / Typeahead.Js",
+ "path": "typeahead-js",
+ "path_with_namespace": "twitter/typeahead-js",
+ "issues_enabled": true,
+ "merge_requests_enabled": true,
+ "wiki_enabled": true,
+ "builds_enabled": true,
+ "snippets_enabled": false,
+ "container_registry_enabled": true,
+ "created_at": "2016-06-17T07:47:25.578Z",
+ "last_activity_at": "2016-06-17T07:47:25.881Z",
+ "shared_runners_enabled": true,
+ "creator_id": 1,
+ "namespace": {
+ "id": 4,
+ "name": "Twitter",
+ "path": "twitter",
+ "owner_id": null,
+ "created_at": "2016-06-17T07:47:24.216Z",
+ "updated_at": "2016-06-17T07:47:24.216Z",
+ "description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.",
+ "avatar": {
+ "url": null
+ },
+ "share_with_group_lock": false,
+ "visibility_level": 20
+ },
+ "avatar_url": null,
+ "star_count": 0,
+ "forks_count": 0,
+ "open_issues_count": 3,
+ "public_builds": true,
+ "shared_with_groups": []
+ },
+ {
+ "id": 6,
+ "description": "Aspernatur omnis repudiandae qui voluptatibus eaque.",
+ "default_branch": "master",
+ "tag_list": [],
+ "public": false,
+ "archived": false,
+ "visibility_level": 10,
+ "ssh_url_to_repo": "git@gitlab.example.com:twitter/flight.git",
+ "http_url_to_repo": "https://gitlab.example.com/twitter/flight.git",
+ "web_url": "https://gitlab.example.com/twitter/flight",
+ "name": "Flight",
+ "name_with_namespace": "Twitter / Flight",
+ "path": "flight",
+ "path_with_namespace": "twitter/flight",
+ "issues_enabled": true,
+ "merge_requests_enabled": true,
+ "wiki_enabled": true,
+ "builds_enabled": true,
+ "snippets_enabled": false,
+ "container_registry_enabled": true,
+ "created_at": "2016-06-17T07:47:24.661Z",
+ "last_activity_at": "2016-06-17T07:47:24.838Z",
+ "shared_runners_enabled": true,
+ "creator_id": 1,
+ "namespace": {
+ "id": 4,
+ "name": "Twitter",
+ "path": "twitter",
+ "owner_id": null,
+ "created_at": "2016-06-17T07:47:24.216Z",
+ "updated_at": "2016-06-17T07:47:24.216Z",
+ "description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.",
+ "avatar": {
+ "url": null
+ },
+ "share_with_group_lock": false,
+ "visibility_level": 20
+ },
+ "avatar_url": null,
+ "star_count": 0,
+ "forks_count": 0,
+ "open_issues_count": 8,
+ "public_builds": true,
+ "shared_with_groups": []
+ }
+ ],
+ "shared_projects": [
+ {
+ "id": 8,
+ "description": "Velit eveniet provident fugiat saepe eligendi autem.",
+ "default_branch": "master",
+ "tag_list": [],
+ "public": false,
+ "archived": false,
+ "visibility_level": 0,
+ "ssh_url_to_repo": "git@gitlab.example.com:h5bp/html5-boilerplate.git",
+ "http_url_to_repo": "https://gitlab.example.com/h5bp/html5-boilerplate.git",
+ "web_url": "https://gitlab.example.com/h5bp/html5-boilerplate",
+ "name": "Html5 Boilerplate",
+ "name_with_namespace": "H5bp / Html5 Boilerplate",
+ "path": "html5-boilerplate",
+ "path_with_namespace": "h5bp/html5-boilerplate",
+ "issues_enabled": true,
+ "merge_requests_enabled": true,
+ "wiki_enabled": true,
+ "builds_enabled": true,
+ "snippets_enabled": false,
+ "container_registry_enabled": true,
+ "created_at": "2016-06-17T07:47:27.089Z",
+ "last_activity_at": "2016-06-17T07:47:27.310Z",
+ "shared_runners_enabled": true,
+ "creator_id": 1,
+ "namespace": {
+ "id": 5,
+ "name": "H5bp",
+ "path": "h5bp",
+ "owner_id": null,
+ "created_at": "2016-06-17T07:47:26.621Z",
+ "updated_at": "2016-06-17T07:47:26.621Z",
+ "description": "Id consequatur rem vel qui doloremque saepe.",
+ "avatar": {
+ "url": null
+ },
+ "share_with_group_lock": false,
+ "visibility_level": 20
+ },
+ "avatar_url": null,
+ "star_count": 0,
+ "forks_count": 0,
+ "open_issues_count": 4,
+ "public_builds": true,
+ "shared_with_groups": [
+ {
+ "group_id": 4,
+ "group_name": "Twitter",
+ "group_access_level": 30
+ },
+ {
+ "group_id": 3,
+ "group_name": "Gitlab Org",
+ "group_access_level": 10
+ }
+ ]
+ }
+ ]
+}
+```
## New group
@@ -201,7 +377,8 @@ Example response:
"star_count": 1,
"forks_count": 0,
"open_issues_count": 3,
- "public_builds": true
+ "public_builds": true,
+ "shared_with_groups": []
}
]
}
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index aee94b3fc36..a8c3b068d22 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -49,10 +49,10 @@ Parameters:
"state": "active",
"created_at": "2012-04-29T08:46:00Z"
},
- "source_project_id": "2",
- "target_project_id": "3",
+ "source_project_id": 2,
+ "target_project_id": 3,
"labels": [ ],
- "description":"fixed login page css paddings",
+ "description": "fixed login page css paddings",
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -68,7 +68,9 @@ Parameters:
"merge_when_build_succeeds": true,
"merge_status": "can_be_merged",
"subscribed" : false,
- "user_notes_count": 1
+ "user_notes_count": 1,
+ "should_remove_source_branch": true,
+ "force_remove_source_branch": false
}
]
```
@@ -113,10 +115,10 @@ Parameters:
"state": "active",
"created_at": "2012-04-29T08:46:00Z"
},
- "source_project_id": "2",
- "target_project_id": "3",
+ "source_project_id": 2,
+ "target_project_id": 3,
"labels": [ ],
- "description":"fixed login page css paddings",
+ "description": "fixed login page css paddings",
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -132,7 +134,9 @@ Parameters:
"merge_when_build_succeeds": true,
"merge_status": "can_be_merged",
"subscribed" : true,
- "user_notes_count": 1
+ "user_notes_count": 1,
+ "should_remove_source_branch": true,
+ "force_remove_source_branch": false
}
```
@@ -233,6 +237,8 @@ Parameters:
"merge_status": "can_be_merged",
"subscribed" : true,
"user_notes_count": 1,
+ "should_remove_source_branch": true,
+ "force_remove_source_branch": false,
"changes": [
{
"old_path": "VERSION",
@@ -296,7 +302,7 @@ Parameters:
"source_project_id": 4,
"target_project_id": 4,
"labels": [ ],
- "description":"fixed login page css paddings",
+ "description": "fixed login page css paddings",
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -312,7 +318,9 @@ Parameters:
"merge_when_build_succeeds": true,
"merge_status": "can_be_merged",
"subscribed" : true,
- "user_notes_count": 0
+ "user_notes_count": 0,
+ "should_remove_source_branch": true,
+ "force_remove_source_branch": false
}
```
@@ -383,7 +391,9 @@ Parameters:
"merge_when_build_succeeds": true,
"merge_status": "can_be_merged",
"subscribed" : true,
- "user_notes_count": 1
+ "user_notes_count": 1,
+ "should_remove_source_branch": true,
+ "force_remove_source_branch": false
}
```
@@ -465,7 +475,7 @@ Parameters:
"source_project_id": 4,
"target_project_id": 4,
"labels": [ ],
- "description":"fixed login page css paddings",
+ "description": "fixed login page css paddings",
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -481,7 +491,9 @@ Parameters:
"merge_when_build_succeeds": true,
"merge_status": "can_be_merged",
"subscribed" : true,
- "user_notes_count": 1
+ "user_notes_count": 1,
+ "should_remove_source_branch": true,
+ "force_remove_source_branch": false
}
```
@@ -531,7 +543,7 @@ Parameters:
"source_project_id": 4,
"target_project_id": 4,
"labels": [ ],
- "description":"fixed login page css paddings",
+ "description": "fixed login page css paddings",
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -547,7 +559,9 @@ Parameters:
"merge_when_build_succeeds": true,
"merge_status": "can_be_merged",
"subscribed" : true,
- "user_notes_count": 1
+ "user_notes_count": 1,
+ "should_remove_source_branch": true,
+ "force_remove_source_branch": false
}
```
@@ -866,7 +880,9 @@ Example response:
"merge_when_build_succeeds": false,
"merge_status": "unchecked",
"subscribed": true,
- "user_notes_count": 7
+ "user_notes_count": 7,
+ "should_remove_source_branch": true,
+ "force_remove_source_branch": false
},
"target_url": "https://gitlab.example.com/gitlab-org/gitlab-ci/merge_requests/7",
"body": "Et voluptas laudantium minus nihil recusandae ut accusamus earum aut non.",
diff --git a/doc/api/projects.md b/doc/api/projects.md
index f5f195b97df..dceee7b4ea7 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -52,7 +52,7 @@ Parameters:
"owner": {
"id": 3,
"name": "Diaspora",
- "created_at": "2013-09-30T13: 46: 02Z"
+ "created_at": "2013-09-30T13:46:02Z"
},
"name": "Diaspora Client",
"name_with_namespace": "Diaspora / Diaspora Client",
@@ -64,17 +64,18 @@ Parameters:
"builds_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
- "created_at": "2013-09-30T13: 46: 02Z",
- "last_activity_at": "2013-09-30T13: 46: 02Z",
+ "container_registry_enabled": false,
+ "created_at": "2013-09-30T13:46:02Z",
+ "last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
- "created_at": "2013-09-30T13: 46: 02Z",
+ "created_at": "2013-09-30T13:46:02Z",
"description": "",
"id": 3,
"name": "Diaspora",
"owner_id": 1,
"path": "diaspora",
- "updated_at": "2013-09-30T13: 46: 02Z"
+ "updated_at": "2013-09-30T13:46:02Z"
},
"archived": false,
"avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png",
@@ -82,7 +83,8 @@ Parameters:
"forks_count": 0,
"star_count": 0,
"runners_token": "b8547b1dc37721d05889db52fa2f02",
- "public_builds": true
+ "public_builds": true,
+ "shared_with_groups": []
},
{
"id": 6,
@@ -112,6 +114,7 @@ Parameters:
"builds_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
+ "container_registry_enabled": false,
"created_at": "2013-09-30T13:46:02Z",
"last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
@@ -140,7 +143,8 @@ Parameters:
"forks_count": 0,
"star_count": 0,
"runners_token": "b8547b1dc37721d05889db52fa2f02",
- "public_builds": true
+ "public_builds": true,
+ "shared_with_groups": []
}
]
```
@@ -223,7 +227,7 @@ Parameters:
"owner": {
"id": 3,
"name": "Diaspora",
- "created_at": "2013-09-30T13: 46: 02Z"
+ "created_at": "2013-09-30T13:46:02Z"
},
"name": "Diaspora Project Site",
"name_with_namespace": "Diaspora / Diaspora Project Site",
@@ -235,17 +239,18 @@ Parameters:
"builds_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
- "created_at": "2013-09-30T13: 46: 02Z",
- "last_activity_at": "2013-09-30T13: 46: 02Z",
+ "container_registry_enabled": false,
+ "created_at": "2013-09-30T13:46:02Z",
+ "last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
- "created_at": "2013-09-30T13: 46: 02Z",
+ "created_at": "2013-09-30T13:46:02Z",
"description": "",
"id": 3,
"name": "Diaspora",
"owner_id": 1,
"path": "diaspora",
- "updated_at": "2013-09-30T13: 46: 02Z"
+ "updated_at": "2013-09-30T13:46:02Z"
},
"permissions": {
"project_access": {
@@ -262,7 +267,20 @@ Parameters:
"shared_runners_enabled": true,
"forks_count": 0,
"star_count": 0,
- "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b"
+ "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
+ "public_builds": true,
+ "shared_with_groups": [
+ {
+ "group_id": 4,
+ "group_name": "Twitter",
+ "group_access_level": 30
+ },
+ {
+ "group_id": 3,
+ "group_name": "Gitlab Org",
+ "group_access_level": 10
+ }
+ ]
}
```
@@ -425,6 +443,7 @@ Parameters:
- `wiki_enabled` (optional)
- `snippets_enabled` (optional)
- `container_registry_enabled` (optional)
+- `shared_runners_enabled` (optional)
- `public` (optional) - if `true` same as setting visibility_level = 20
- `visibility_level` (optional)
- `import_url` (optional)
@@ -449,6 +468,7 @@ Parameters:
- `wiki_enabled` (optional)
- `snippets_enabled` (optional)
- `container_registry_enabled` (optional)
+- `shared_runners_enabled` (optional)
- `public` (optional) - if `true` same as setting visibility_level = 20
- `visibility_level` (optional)
- `import_url` (optional)
@@ -475,6 +495,7 @@ Parameters:
- `wiki_enabled` (optional)
- `snippets_enabled` (optional)
- `container_registry_enabled` (optional)
+- `shared_runners_enabled` (optional)
- `public` (optional) - if `true` same as setting visibility_level = 20
- `visibility_level` (optional)
- `public_builds` (optional)
@@ -537,23 +558,26 @@ Example response:
"builds_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
- "created_at": "2013-09-30T13: 46: 02Z",
- "last_activity_at": "2013-09-30T13: 46: 02Z",
+ "container_registry_enabled": false,
+ "created_at": "2013-09-30T13:46:02Z",
+ "last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
- "created_at": "2013-09-30T13: 46: 02Z",
+ "created_at": "2013-09-30T13:46:02Z",
"description": "",
"id": 3,
"name": "Diaspora",
"owner_id": 1,
"path": "diaspora",
- "updated_at": "2013-09-30T13: 46: 02Z"
+ "updated_at": "2013-09-30T13:46:02Z"
},
"archived": true,
"avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png",
"shared_runners_enabled": true,
"forks_count": 0,
- "star_count": 1
+ "star_count": 1,
+ "public_builds": true,
+ "shared_with_groups": []
}
```
@@ -600,23 +624,26 @@ Example response:
"builds_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
- "created_at": "2013-09-30T13: 46: 02Z",
- "last_activity_at": "2013-09-30T13: 46: 02Z",
+ "container_registry_enabled": false,
+ "created_at": "2013-09-30T13:46:02Z",
+ "last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
- "created_at": "2013-09-30T13: 46: 02Z",
+ "created_at": "2013-09-30T13:46:02Z",
"description": "",
"id": 3,
"name": "Diaspora",
"owner_id": 1,
"path": "diaspora",
- "updated_at": "2013-09-30T13: 46: 02Z"
+ "updated_at": "2013-09-30T13:46:02Z"
},
"archived": true,
"avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png",
"shared_runners_enabled": true,
"forks_count": 0,
- "star_count": 0
+ "star_count": 0,
+ "public_builds": true,
+ "shared_with_groups": []
}
```
@@ -660,7 +687,7 @@ Example response:
"owner": {
"id": 3,
"name": "Diaspora",
- "created_at": "2013-09-30T13: 46: 02Z"
+ "created_at": "2013-09-30T13:46:02Z"
},
"name": "Diaspora Project Site",
"name_with_namespace": "Diaspora / Diaspora Project Site",
@@ -672,17 +699,18 @@ Example response:
"builds_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
- "created_at": "2013-09-30T13: 46: 02Z",
- "last_activity_at": "2013-09-30T13: 46: 02Z",
+ "container_registry_enabled": false,
+ "created_at": "2013-09-30T13:46:02Z",
+ "last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
- "created_at": "2013-09-30T13: 46: 02Z",
+ "created_at": "2013-09-30T13:46:02Z",
"description": "",
"id": 3,
"name": "Diaspora",
"owner_id": 1,
"path": "diaspora",
- "updated_at": "2013-09-30T13: 46: 02Z"
+ "updated_at": "2013-09-30T13:46:02Z"
},
"permissions": {
"project_access": {
@@ -699,7 +727,9 @@ Example response:
"shared_runners_enabled": true,
"forks_count": 0,
"star_count": 0,
- "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b"
+ "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
+ "public_builds": true,
+ "shared_with_groups": []
}
```
@@ -713,7 +743,7 @@ have the proper access rights, code 403 is returned. Status 404 is returned if t
doesn't exist, or is hidden to the user.
```
-POST /projects/:id/archive
+POST /projects/:id/unarchive
```
| Attribute | Type | Required | Description |
@@ -743,7 +773,7 @@ Example response:
"owner": {
"id": 3,
"name": "Diaspora",
- "created_at": "2013-09-30T13: 46: 02Z"
+ "created_at": "2013-09-30T13:46:02Z"
},
"name": "Diaspora Project Site",
"name_with_namespace": "Diaspora / Diaspora Project Site",
@@ -755,17 +785,18 @@ Example response:
"builds_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
- "created_at": "2013-09-30T13: 46: 02Z",
- "last_activity_at": "2013-09-30T13: 46: 02Z",
+ "container_registry_enabled": false,
+ "created_at": "2013-09-30T13:46:02Z",
+ "last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
- "created_at": "2013-09-30T13: 46: 02Z",
+ "created_at": "2013-09-30T13:46:02Z",
"description": "",
"id": 3,
"name": "Diaspora",
"owner_id": 1,
"path": "diaspora",
- "updated_at": "2013-09-30T13: 46: 02Z"
+ "updated_at": "2013-09-30T13:46:02Z"
},
"permissions": {
"project_access": {
@@ -782,7 +813,9 @@ Example response:
"shared_runners_enabled": true,
"forks_count": 0,
"star_count": 0,
- "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b"
+ "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
+ "public_builds": true,
+ "shared_with_groups": []
}
```
@@ -965,11 +998,11 @@ Parameters:
"id": 1,
"url": "http://example.com/hook",
"project_id": 3,
- "push_events": "true",
- "issues_events": "true",
- "merge_requests_events": "true",
- "note_events": "true",
- "enable_ssl_verification": "true",
+ "push_events": true,
+ "issues_events": true,
+ "merge_requests_events": true,
+ "note_events": true,
+ "enable_ssl_verification": true,
"created_at": "2012-10-12T17:04:47Z"
}
```
@@ -1089,8 +1122,8 @@ Parameters:
"name": "Jeremy Ashkenas",
"email": "jashkenas@example.com"
},
- "authored_date": "2013-09-07T12: 58: 21+00: 00",
- "committed_date": "2013-09-07T12: 58: 21+00: 00"
+ "authored_date": "2013-09-07T12:58:21+00:00",
+ "committed_date": "2013-09-07T12:58:21+00:00"
},
"protected": false
}
diff --git a/doc/api/settings.md b/doc/api/settings.md
index 741c5a29581..d9b68eaeadf 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -68,6 +68,7 @@ PUT /application/settings
| `after_sign_out_path` | string | no | Where to redirect users after logout |
| `container_registry_token_expire_delay` | integer | no | Container Registry token duration in minutes |
| `repository_storage` | string | no | Storage path for new projects. The value should be the name of one of the repository storage paths defined in your gitlab.yml |
+| `enabled_git_access_protocol` | string | no | Enabled protocols for Git access. Allowed values are: `ssh`, `http`, and `nil` to allow both protocols.
```bash
curl -X PUT -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/application/settings?signup_enabled=false&default_project_visibility=1
diff --git a/doc/ci/examples/php.md b/doc/ci/examples/php.md
index 17e1c64bb8a..bfafcc44d66 100644
--- a/doc/ci/examples/php.md
+++ b/doc/ci/examples/php.md
@@ -49,7 +49,7 @@ apt-get update -yqq
apt-get install git -yqq
# Install phpunit, the tool that we will use for testing
-curl -o /usr/local/bin/phpunit https://phar.phpunit.de/phpunit.phar
+curl -Lo /usr/local/bin/phpunit https://phar.phpunit.de/phpunit.phar
chmod +x /usr/local/bin/phpunit
# Install mysql driver
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index d2d1b04f893..16a1461a7e4 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -133,7 +133,7 @@ builds, including deploy builds. This can be an array or a multi-line string.
### after_script
>**Note:**
-Introduced in GitLab 8.7 and requires Gitlab Runner v1.2 (not yet released)
+Introduced in GitLab 8.7 and requires Gitlab Runner v1.2
`after_script` is used to define the command that will be run after for all
builds. This has to be an array or a multi-line string.
@@ -811,7 +811,7 @@ deploy:
It's possible to overwrite globally defined `before_script` and `after_script`:
```yaml
-before_script
+before_script:
- global before script
job:
diff --git a/doc/development/ui_guide.md b/doc/development/ui_guide.md
index 5893b7c219e..8d02c52c477 100644
--- a/doc/development/ui_guide.md
+++ b/doc/development/ui_guide.md
@@ -27,6 +27,8 @@ We try to keep the amount of tabs in the header navigation between 5 and 10 so t
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
@@ -52,5 +54,6 @@ information from database or file system
* 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
+* 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"
diff --git a/doc/hooks/custom_hooks.md b/doc/hooks/custom_hooks.md
index 820934f97f1..1d5e5dd6e15 100644
--- a/doc/hooks/custom_hooks.md
+++ b/doc/hooks/custom_hooks.md
@@ -1,41 +1,3 @@
# Custom Git Hooks
-**Note: Custom git hooks must be configured on the filesystem of the GitLab
-server. Only GitLab server administrators will be able to complete these tasks.
-Please explore [webhooks](../web_hooks/web_hooks.md) as an option if you do not have filesystem access. For a user configurable Git Hooks interface, please see [GitLab Enterprise Edition Git Hooks](http://docs.gitlab.com/ee/git_hooks/git_hooks.html).**
-
-Git natively supports hooks that are executed on different actions.
-Examples of server-side git hooks include pre-receive, post-receive, and update.
-See
-[Git SCM Server-Side Hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#Server-Side-Hooks)
-for more information about each hook type.
-
-As of gitlab-shell version 2.2.0 (which requires GitLab 7.5+), GitLab
-administrators can add custom git hooks to any GitLab project.
-
-## Setup
-
-Normally, git hooks are placed in the repository or project's `hooks` directory.
-GitLab creates a symlink from each project's `hooks` directory to the
-gitlab-shell `hooks` directory for ease of maintenance between gitlab-shell
-upgrades. As such, custom hooks are implemented a little differently. Behavior
-is exactly the same once the hook is created, though. Follow these steps to
-set up a custom hook.
-
-1. Pick a project that needs a custom git hook.
-1. On the GitLab server, navigate to the project's repository directory.
-For an installation from source the path is usually
-`/home/git/repositories/<group>/<project>.git`. For Omnibus installs the path is
-usually `/var/opt/gitlab/git-data/repositories/<group>/<project>.git`.
-1. Create a new directory in this location called `custom_hooks`.
-1. Inside the new `custom_hooks` directory, create a file with a name matching
-the hook type. For a pre-receive hook the file name should be `pre-receive` with
-no extension.
-1. Make the hook file executable and make sure it's owned by git.
-1. Write the code to make the git hook function as expected. Hooks can be
-in any language. Ensure the 'shebang' at the top properly reflects the language
-type. For example, if the script is in Ruby the shebang will probably be
-`#!/usr/bin/env ruby`.
-
-That's it! Assuming the hook code is properly implemented the hook will fire
-as appropriate.
+This document was moved to [administration/custom_hooks.md](../administration/custom_hooks.md).
diff --git a/doc/install/database_mysql.md b/doc/install/database_mysql.md
index e51ff5a5de2..e8093f0b257 100644
--- a/doc/install/database_mysql.md
+++ b/doc/install/database_mysql.md
@@ -36,7 +36,7 @@ We do not recommend using MySQL due to various issues. For example, case [(in)se
mysql> CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`;
# Grant the GitLab user necessary permissions on the database
- mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, CREATE TEMPORARY TABLES, DROP, INDEX, ALTER, LOCK TABLES ON `gitlabhq_production`.* TO 'git'@'localhost';
+ mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, CREATE TEMPORARY TABLES, DROP, INDEX, ALTER, LOCK TABLES, REFERENCES ON `gitlabhq_production`.* TO 'git'@'localhost';
# Quit the database session
mysql> \q
diff --git a/doc/install/installation.md b/doc/install/installation.md
index dc8d9c65535..19d083d580d 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -269,9 +269,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 8-9-stable gitlab
+ sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 8-10-stable gitlab
-**Note:** You can change `8-9-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
+**Note:** You can change `8-10-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
### Configure It
@@ -398,7 +398,7 @@ If you are not using Linux you may have to run `gmake` instead of
cd /home/git
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git
cd gitlab-workhorse
- sudo -u git -H git checkout v0.7.5
+ sudo -u git -H git checkout v0.7.7
sudo -u git -H make
### Initialize Database and Activate Advanced Features
diff --git a/doc/integration/github.md b/doc/integration/github.md
index e7497e475c9..340c8a55fb3 100644
--- a/doc/integration/github.md
+++ b/doc/integration/github.md
@@ -19,7 +19,7 @@ GitHub will generate an application ID and secret key for you to use.
- 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'
- Application description: Fill this in if you wish.
- - Default authorization callback URL is '${YOUR_DOMAIN}/import/github/callback'
+ - Authorization callback URL is 'http(s)://${YOUR_DOMAIN}'
1. Select "Register application".
1. You should now see a Client ID and Client Secret near the top right of the page (see screenshot).
diff --git a/doc/integration/shibboleth.md b/doc/integration/shibboleth.md
index b6b2d4e5e88..5210ce0de9a 100644
--- a/doc/integration/shibboleth.md
+++ b/doc/integration/shibboleth.md
@@ -2,7 +2,7 @@
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 I did not found way to easily configure Nginx that is bundled in omnibus-gitlab package). Apache uses mod_shib2 module for shibboleth authentication and can pass attributes as headers to omniauth-shibboleth provider.
+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 NIGNX 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:
diff --git a/doc/markdown/markdown.md b/doc/markdown/markdown.md
index 236eb7b12c4..fb2dd582754 100644
--- a/doc/markdown/markdown.md
+++ b/doc/markdown/markdown.md
@@ -7,11 +7,12 @@
* [Newlines](#newlines)
* [Multiple underscores in words](#multiple-underscores-in-words)
* [URL auto-linking](#url-auto-linking)
+* [Multiline Blockquote](#multiline-blockquote)
* [Code and Syntax Highlighting](#code-and-syntax-highlighting)
* [Inline Diff](#inline-diff)
* [Emoji](#emoji)
* [Special GitLab references](#special-gitlab-references)
-* [Task lists](#task-lists)
+* [Task Lists](#task-lists)
**[Standard Markdown](#standard-markdown)**
@@ -89,6 +90,37 @@ GFM will autolink almost any URL you copy and paste into your text.
* irc://irc.freenode.net/gitlab
* http://localhost:3000
+## Multiline Blockquote
+
+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
+
+that
+
+spans
+
+multiple lines,
+
+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!
+>>>
+
## Code and Syntax Highlighting
_GitLab uses the [Rouge Ruby library][rouge] for syntax highlighting. For a
diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md
index 963b35de3a0..44f3f6d3b12 100644
--- a/doc/permissions/permissions.md
+++ b/doc/permissions/permissions.md
@@ -99,3 +99,6 @@ 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
will find the option to flag the user as external.
+
+By default new users are not set as external users. This behavior can be changed
+by an administrator under **Admin > Application Settings**. \ No newline at end of file
diff --git a/doc/update/8.8-to-8.9.md b/doc/update/8.8-to-8.9.md
index 423140a92c7..f078a2bece5 100644
--- a/doc/update/8.8-to-8.9.md
+++ b/doc/update/8.8-to-8.9.md
@@ -62,7 +62,23 @@ sudo -u git -H git checkout v0.7.5
sudo -u git -H make
```
-### 6. Install libs, migrations, etc.
+### 6. Update MySQL permissions
+
+If you are using MySQL you need to grant the GitLab user the necessary
+permissions on the database:
+
+```bash
+# Login to MySQL
+mysql -u root -p
+
+# Grant the GitLab user the REFERENCES permission on the database
+GRANT REFERENCES ON `gitlabhq_production`.* TO 'git'@'localhost';
+
+# Quit the database session
+mysql> \q
+```
+
+### 7. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
@@ -84,7 +100,7 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS
```
-### 7. Update configuration files
+### 8. Update configuration files
#### New configuration options for `gitlab.yml`
@@ -141,12 +157,12 @@ Ensure you're still up-to-date with the latest init script changes:
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-### 8. Start application
+### 9. Start application
sudo service gitlab start
sudo service nginx restart
-### 9. Check application status
+### 10. Check application status
Check if GitLab and its environment are configured correctly:
diff --git a/doc/update/8.9-to-8.10.md b/doc/update/8.9-to-8.10.md
new file mode 100644
index 00000000000..84065a84e50
--- /dev/null
+++ b/doc/update/8.9-to-8.10.md
@@ -0,0 +1,191 @@
+# From 8.9 to 8.10
+
+Make sure you view this update guide from the tag (version) of GitLab you would
+like to install. In most cases this should be the highest numbered production
+tag (without rc in it). You can select the tag 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
+
+ sudo service gitlab stop
+
+### 2. Backup
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 3. Get latest code
+
+```bash
+sudo -u git -H git fetch --all
+sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
+```
+
+For GitLab Community Edition:
+
+```bash
+sudo -u git -H git checkout 8-10-stable
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+sudo -u git -H git checkout 8-10-stable-ee
+```
+
+### 4. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v3.2.0
+```
+
+### 5. Update gitlab-workhorse
+
+Install and compile gitlab-workhorse. This requires
+[Go 1.5](https://golang.org/dl) which should already be on your system from
+GitLab 8.1.
+
+```bash
+cd /home/git/gitlab-workhorse
+sudo -u git -H git fetch --all
+sudo -u git -H git checkout v0.7.7
+sudo -u git -H make
+```
+
+### 6. Update MySQL permissions
+
+If you are using MySQL you need to grant the GitLab user the necessary
+permissions on the database:
+
+```bash
+# Login to MySQL
+mysql -u root -p
+
+# Grant the GitLab user the REFERENCES permission on the database
+GRANT REFERENCES ON `gitlabhq_production`.* TO 'git'@'localhost';
+
+# Quit the database session
+mysql> \q
+```
+
+### 7. 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
+
+# Clean up assets and cache
+sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
+
+```
+
+### 8. Update configuration files
+
+#### New configuration options for `gitlab.yml`
+
+There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
+
+```sh
+git diff origin/8-9-stable:config/gitlab.yml.example origin/8-10-stable:config/gitlab.yml.example
+```
+
+#### Git configuration
+
+Disable `git gc --auto` because GitLab runs `git gc` for us already.
+
+```sh
+sudo -u git -H git config --global gc.auto 0
+```
+
+#### Nginx configuration
+
+Ensure you're still up-to-date with the latest NGINX configuration changes:
+
+```sh
+# For HTTPS configurations
+git diff origin/8-9-stable:lib/support/nginx/gitlab-ssl origin/8-10-stable:lib/support/nginx/gitlab-ssl
+
+# For HTTP configurations
+git diff origin/8-9-stable:lib/support/nginx/gitlab origin/8-10-stable:lib/support/nginx/gitlab
+```
+
+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/8-10-stable/lib/support/init.d/gitlab.default.example#L37
+
+#### 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/v8.9.0/config/initializers/smtp_settings.rb.sample#L13
+
+#### Init script
+
+Ensure you're still up-to-date with the latest init script changes:
+
+ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+
+### 9. Start application
+
+ sudo service gitlab start
+ sudo service nginx restart
+
+### 10. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+ 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:
+
+ 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 (8.9)
+
+### 1. Revert the code to the previous version
+
+Follow the [upgrade guide from 8.8 to 8.9](8.8-to-8.9.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.
diff --git a/doc/workflow/protected_branches.md b/doc/workflow/protected_branches.md
index d854ec1e025..67adfc2f43a 100644
--- a/doc/workflow/protected_branches.md
+++ b/doc/workflow/protected_branches.md
@@ -1,4 +1,4 @@
-# Protected branches
+# Protected Branches
Permissions in GitLab are fundamentally defined around the idea of having read or write permission to the repository and branches.
@@ -28,4 +28,28 @@ For those workflows, you can allow everyone with write access to push to a prote
On already protected branches you can also allow developers to push to the repository by selecting the `Developers can push` check box.
-![Developers can push](protected_branches/protected_branches2.png) \ No newline at end of file
+![Developers can push](protected_branches/protected_branches2.png)
+
+## Wildcard Protected Branches
+
+>**Note:**
+This feature was added in GitLab 8.10.
+
+1. You can specify a wildcard protected branch, which will protect all branches matching the wildcard. For example:
+
+ | Wildcard Protected Branch | Matching Branches |
+ |---------------------------+--------------------------------------------------------|
+ | `*-stable` | `production-stable`, `staging-stable` |
+ | `production/*` | `production/app-server`, `production/load-balancer` |
+ | `*gitlab*` | `gitlab`, `gitlab/staging`, `master/gitlab/production` |
+
+1. Protected branch settings (like "Developers Can Push") apply to all matching branches.
+
+1. Two different wildcards can potentially match the same branch. For example, `*-stable` and `production-*` would both match a `production-stable` branch.
+ >**Note:**
+ If _any_ of these protected branches have "Developers Can Push" set to true, then `production-stable` has it set to true.
+
+1. If you click on a protected branch's name, you will be presented with a list of all matching branches:
+
+ ![protected branch matches](protected_branches/protected_branches3.png)
+
diff --git a/doc/workflow/protected_branches/protected_branches1.png b/doc/workflow/protected_branches/protected_branches1.png
index bb3ab7d7913..c00443803de 100644
--- a/doc/workflow/protected_branches/protected_branches1.png
+++ b/doc/workflow/protected_branches/protected_branches1.png
Binary files differ
diff --git a/doc/workflow/protected_branches/protected_branches2.png b/doc/workflow/protected_branches/protected_branches2.png
index 58ace31ac57..a4f664d3b21 100644
--- a/doc/workflow/protected_branches/protected_branches2.png
+++ b/doc/workflow/protected_branches/protected_branches2.png
Binary files differ
diff --git a/doc/workflow/protected_branches/protected_branches3.png b/doc/workflow/protected_branches/protected_branches3.png
new file mode 100644
index 00000000000..2a50cb174bb
--- /dev/null
+++ b/doc/workflow/protected_branches/protected_branches3.png
Binary files differ
diff --git a/features/admin/projects.feature b/features/admin/projects.feature
index c5ee80136c8..8929bcf8d80 100644
--- a/features/admin/projects.feature
+++ b/features/admin/projects.feature
@@ -10,10 +10,11 @@ Feature: Admin Projects
Then I should see all non-archived projects
And I should not see project "Archive"
+ @javascript
Scenario: I should see all projects in the list
Given archived project "Archive"
When I visit admin projects page
- And I check "Show archived projects"
+ And I select "Show archived projects"
Then I should see all projects
And I should see "archived" label
@@ -22,6 +23,7 @@ Feature: Admin Projects
And I click on first project
Then I should see project details
+ @javascript
Scenario: Transfer project
Given group 'Web'
And I visit admin project page
diff --git a/features/dashboard/dashboard.feature b/features/dashboard/dashboard.feature
index db73309804c..1f4c9020731 100644
--- a/features/dashboard/dashboard.feature
+++ b/features/dashboard/dashboard.feature
@@ -7,6 +7,7 @@ Feature: Dashboard
And project "Shop" has CI enabled
And project "Shop" has CI build
And project "Shop" has labels: "bug", "feature", "enhancement"
+ And project "Shop" has issue: "bug report"
And I visit dashboard page
Scenario: I should see projects list
diff --git a/features/project/commits/commits.feature b/features/project/commits/commits.feature
index a95df038357..8b0cb90765e 100644
--- a/features/project/commits/commits.feature
+++ b/features/project/commits/commits.feature
@@ -83,11 +83,6 @@ Feature: Project Commits
#Given I visit my project's commits stats page
#Then I see commits stats
- Scenario: I browse big commit
- Given I visit big commit page
- Then I see big commit warning
- And I see "Reload with full diff" link
-
Scenario: I browse a commit with an image
Given I visit a commit with an image that changed
Then The diff links to both the previous and current image
diff --git a/features/project/commits/diff_comments.feature b/features/project/commits/diff_comments.feature
index 2bde4c8a99b..35687aac9ea 100644
--- a/features/project/commits/diff_comments.feature
+++ b/features/project/commits/diff_comments.feature
@@ -6,10 +6,6 @@ Feature: Project Commits Diff Comments
And I visit project commit page
@javascript
- Scenario: I can access add diff comment buttons
- Then I should see add a diff comment button
-
- @javascript
Scenario: I can comment on a commit diff
Given I leave a diff comment like "Typo, please fix"
Then I should see a diff comment saying "Typo, please fix"
diff --git a/features/project/merge_requests.feature b/features/project/merge_requests.feature
index 0e97e4d5954..21768c15c17 100644
--- a/features/project/merge_requests.feature
+++ b/features/project/merge_requests.feature
@@ -89,13 +89,6 @@ Feature: Project Merge Requests
Then The list should be sorted by "Oldest updated"
@javascript
- Scenario: Visiting Issues after being sorted the list
- Given I visit project "Shop" merge requests page
- And I sort the list by "Oldest updated"
- And I visit project "Shop" issues page
- Then The list should be sorted by "Oldest updated"
-
- @javascript
Scenario: Visiting Merge Requests from a differente Project after sorting
Given I visit project "Shop" merge requests page
And I sort the list by "Oldest updated"
diff --git a/features/steps/admin/groups.rb b/features/steps/admin/groups.rb
index 8613dc537cc..0c89a3db9ad 100644
--- a/features/steps/admin/groups.rb
+++ b/features/steps/admin/groups.rb
@@ -62,7 +62,8 @@ class Spinach::Features::AdminGroups < Spinach::FeatureSteps
step 'I should see "johndoe@gitlab.com" in team list in every project as "Reporter"' do
page.within ".group-users-list" do
- expect(page).to have_content "johndoe@gitlab.com – Invited by"
+ expect(page).to have_content "johndoe@gitlab.com"
+ expect(page).to have_content "Invited by"
expect(page).to have_content "Reporter"
end
end
diff --git a/features/steps/admin/projects.rb b/features/steps/admin/projects.rb
index a7a28755a6c..d77945a6b9c 100644
--- a/features/steps/admin/projects.rb
+++ b/features/steps/admin/projects.rb
@@ -18,9 +18,9 @@ class Spinach::Features::AdminProjects < Spinach::FeatureSteps
end
end
- step 'I check "Show archived projects"' do
- page.check 'Show archived projects'
- click_button "Search"
+ step 'I select "Show archived projects"' do
+ find(:css, '#sort-projects-dropdown').click
+ click_link 'Show archived projects'
end
step 'I should see "archived" label' do
@@ -45,7 +45,8 @@ class Spinach::Features::AdminProjects < Spinach::FeatureSteps
step 'I transfer project to group \'Web\'' do
allow_any_instance_of(Projects::TransferService).
to receive(:move_uploads_to_new_namespace).and_return(true)
- find(:xpath, "//input[@id='new_namespace_id']").set group.id
+ click_button 'Search for Namespace'
+ click_link 'group: web'
click_button 'Transfer'
end
diff --git a/features/steps/dashboard/help.rb b/features/steps/dashboard/help.rb
index 800e869533e..9c94dc70df0 100644
--- a/features/steps/dashboard/help.rb
+++ b/features/steps/dashboard/help.rb
@@ -8,7 +8,7 @@ class Spinach::Features::DashboardHelp < Spinach::FeatureSteps
end
step 'I visit the "Rake Tasks" help page' do
- visit help_page_path("raketasks", "maintenance")
+ visit help_page_path("raketasks/maintenance")
end
step 'I should see "Rake Tasks" page markdown rendered' do
diff --git a/features/steps/profile/profile.rb b/features/steps/profile/profile.rb
index 9e5602dacf1..4ee6784a086 100644
--- a/features/steps/profile/profile.rb
+++ b/features/steps/profile/profile.rb
@@ -155,8 +155,11 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
end
step 'I click on my profile picture' do
- find(:css, '.side-nav-toggle').click
- find(:css, '.sidebar-user').click
+ find(:css, '.header-user-dropdown-toggle').click
+
+ page.within ".header-user" do
+ click_link "Profile"
+ end
end
step 'I should see my user page' do
diff --git a/features/steps/project/builds/artifacts.rb b/features/steps/project/builds/artifacts.rb
index 2876e8812e9..b4a32ed2e38 100644
--- a/features/steps/project/builds/artifacts.rb
+++ b/features/steps/project/builds/artifacts.rb
@@ -68,10 +68,16 @@ class Spinach::Features::ProjectBuildsArtifacts < Spinach::FeatureSteps
end
step 'download of a file extracted from build artifacts should start' do
- # this will be accelerated by Workhorse
- response_json = JSON.parse(page.body, symbolize_names: true)
- expect(response_json[:archive]).to end_with('build_artifacts.zip')
- expect(response_json[:entry]).to eq Base64.encode64('ci_artifacts.txt')
+ send_data = response_headers[Gitlab::Workhorse::SEND_DATA_HEADER]
+
+ expect(send_data).to start_with('artifacts-entry:')
+
+ base64_params = send_data.sub(/\Aartifacts\-entry:/, '')
+ params = JSON.parse(Base64.urlsafe_decode64(base64_params))
+
+ expect(params.keys).to eq(['Archive', 'Entry'])
+ expect(params['Archive']).to end_with('build_artifacts.zip')
+ expect(params['Entry']).to eq(Base64.encode64('ci_artifacts.txt'))
end
step 'I click a first row within build artifacts table' do
diff --git a/features/steps/project/commits/commits.rb b/features/steps/project/commits/commits.rb
index 239036e431d..bea9f9d198b 100644
--- a/features/steps/project/commits/commits.rb
+++ b/features/steps/project/commits/commits.rb
@@ -125,25 +125,6 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps
expect(page).to have_content 'Authors'
end
- step 'I visit big commit page' do
- # Create a temporary scope to ensure that the stub_const is removed after user
- RSpec::Mocks.with_temporary_scope do
- stub_const('Gitlab::Git::DiffCollection::DEFAULT_LIMITS', { max_lines: 1, max_files: 1 })
- visit namespace_project_commit_path(@project.namespace, @project, sample_big_commit.id)
- end
- end
-
- step 'I see big commit warning' do
- expect(page).to have_content sample_big_commit.message
- expect(page).to have_content "Too many changes"
- end
-
- step 'I see "Reload with full diff" link' do
- link = find_link('Reload with full diff')
- expect(link[:href]).to end_with('?force_show_diff=true')
- expect(link[:href]).not_to include('.html')
- end
-
step 'I visit a commit with an image that changed' do
visit namespace_project_commit_path(@project.namespace, @project, sample_image_commit.id)
end
diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb
index 640f1720a6c..da848afd48e 100644
--- a/features/steps/project/merge_requests.rb
+++ b/features/steps/project/merge_requests.rb
@@ -272,10 +272,9 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
step 'user "John Doe" leaves a comment like "Line is wrong" on diff' do
mr = MergeRequest.find_by(title: "Bug NS-05")
- create(:note_on_merge_request_diff, project: project,
+ create(:diff_note_on_merge_request, project: project,
noteable: mr,
author: user_exists("John Doe"),
- line_code: sample_commit.line_code,
note: 'Line is wrong')
end
@@ -519,7 +518,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
step '"Bug NS-05" has CI status' do
project = merge_request.source_project
project.enable_ci
- pipeline = create :ci_pipeline, project: project, sha: merge_request.last_commit.id, ref: merge_request.source_branch
+ pipeline = create :ci_pipeline, project: project, sha: merge_request.diff_head_sha, ref: merge_request.source_branch
create :ci_build, pipeline: pipeline
end
diff --git a/features/steps/shared/diff_note.rb b/features/steps/shared/diff_note.rb
index e8b1e4b4879..4df4e89f5b9 100644
--- a/features/steps/shared/diff_note.rb
+++ b/features/steps/shared/diff_note.rb
@@ -23,27 +23,26 @@ module SharedDiffNote
page.within(diff_file_selector) do
click_diff_line(sample_commit.line_code)
- page.within("form[id$='#{sample_commit.line_code}-true']") do
+ page.within("form[data-line-code='#{sample_commit.line_code}']") do
fill_in "note[note]", with: "Typo, please fix"
- find(".js-comment-button").trigger("click")
- sleep 0.05
+ find(".js-comment-button").click
end
end
end
step 'I leave a diff comment in a parallel view on the left side like "Old comment"' do
- click_parallel_diff_line(sample_commit.line_code, 'old')
- page.within("#{diff_file_selector} form[id$='#{sample_commit.line_code}-true']") do
+ click_parallel_diff_line(sample_commit.del_line_code, 'old')
+ page.within("#{diff_file_selector} form[data-line-code='#{sample_commit.del_line_code}']") do
fill_in "note[note]", with: "Old comment"
- find(".js-comment-button").trigger("click")
+ find(".js-comment-button").click
end
end
step 'I leave a diff comment in a parallel view on the right side like "New comment"' do
click_parallel_diff_line(sample_commit.line_code, 'new')
- page.within("#{diff_file_selector} form[id$='#{sample_commit.line_code}-true']") do
+ page.within("#{diff_file_selector} form[data-line-code='#{sample_commit.line_code}']") do
fill_in "note[note]", with: "New comment"
- find(".js-comment-button").trigger("click")
+ find(".js-comment-button").click
end
end
@@ -51,7 +50,7 @@ module SharedDiffNote
page.within(diff_file_selector) do
click_diff_line(sample_commit.line_code)
- page.within("form[id$='#{sample_commit.line_code}-true']") do
+ page.within("form[data-line-code='#{sample_commit.line_code}']") do
fill_in "note[note]", with: "Should fix it :smile:"
find('.js-md-preview-button').click
end
@@ -62,7 +61,7 @@ module SharedDiffNote
page.within(diff_file_selector) do
click_diff_line(sample_commit.del_line_code)
- page.within("form[id$='#{sample_commit.del_line_code}-true']") do
+ page.within("form[data-line-code='#{sample_commit.del_line_code}']") do
fill_in "note[note]", with: "DRY this up"
find('.js-md-preview-button').click
end
@@ -91,7 +90,7 @@ module SharedDiffNote
page.within(diff_file_selector) do
click_diff_line(sample_commit.line_code)
- page.within("form[id$='#{sample_commit.line_code}-true']") do
+ page.within("form[data-line-code='#{sample_commit.line_code}']") do
fill_in 'note[note]', with: ':smile:'
click_button('Comment')
end
@@ -165,10 +164,6 @@ module SharedDiffNote
end
end
- step 'I should see add a diff comment button' do
- expect(page).to have_css('.js-add-diff-note-button')
- end
-
step 'I should see an empty diff comment form' do
page.within(diff_file_selector) do
expect(page).to have_field("note[note]", with: "")
@@ -215,7 +210,7 @@ module SharedDiffNote
end
step 'I click side-by-side diff button' do
- find('#parallel-diff-btn').trigger('click')
+ find('#parallel-diff-btn').click
end
step 'I see side-by-side diff button' do
@@ -227,10 +222,12 @@ module SharedDiffNote
end
def click_diff_line(code)
- find("button[data-line-code='#{code}']").trigger('click')
+ find(".line_holder[id='#{code}'] td:nth-of-type(1)").trigger 'mouseover'
+ find(".line_holder[id='#{code}'] button").trigger 'click'
end
def click_parallel_diff_line(code, line_type)
- find("button[data-line-code='#{code}'][data-line-type='#{line_type}']").trigger('click')
+ find(".line_content.parallel.#{line_type}[data-line-code='#{code}']").trigger 'mouseover'
+ find(".line_holder.parallel button[data-line-code='#{code}']").trigger 'click'
end
end
diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb
index b3411c03118..0b4920883b8 100644
--- a/features/steps/shared/project.rb
+++ b/features/steps/shared/project.rb
@@ -223,6 +223,11 @@ module SharedProject
create(:label, project: project, title: 'enhancement')
end
+ step 'project "Shop" has issue: "bug report"' do
+ project = Project.find_by(name: "Shop")
+ create(:issue, project: project, title: "bug report")
+ end
+
step 'project "Shop" has CI enabled' do
project = Project.find_by(name: "Shop")
project.enable_ci
diff --git a/fixtures/emojis/digests.json b/fixtures/emojis/digests.json
index 41ca617847e..50ee5089d8f 100644
--- a/fixtures/emojis/digests.json
+++ b/fixtures/emojis/digests.json
@@ -2,62 +2,62 @@
{
"name": "100",
"unicode": "1F4AF",
- "digest": "6d57c7cc93335f853e1a5670233f121bc94730dbd82b2b3c5c5a509e092ef0fd"
+ "digest": "add3bd7d06b6dd445788b277f8c9e5dcf42a54d3ec8b7fb9e7a39695dd95d094"
},
{
"name": "1234",
"unicode": "1F522",
- "digest": "727763fd9f18fd5df59e9f78e678ea4ec753e674d70f15d4e77c7802067d660b"
+ "digest": "c5ac5c8147f5bfd644fad6b470432bba86ffc7bcee04a0e0d277cd1ca485207f"
},
{
"name": "8ball",
"unicode": "1F3B1",
- "digest": "1aecf21951452ba24e921ec71b3d313b7ddc2e185b0339c9e0eebc85be4f031d"
+ "digest": "a6e6855775b66c505adee65926a264103ebddf2e2d963db7c009b4fec3a24178"
},
{
"name": "a",
"unicode": "1F170",
- "digest": "2272113a5bcb7faf8db7c1bd35df576d32f2f7cbd881463934ad3382eb87c723"
+ "digest": "bddbb39e8a1d35d42b7c08e7d47f63988cb4d8614b79f74e70b9c67c221896cc"
},
{
"name": "ab",
"unicode": "1F18E",
- "digest": "6f8a237751fdc84db4121f408272d9a23258515449610e4c6c54f50f6e995627"
+ "digest": "67430fe5fce981160e2ea9052962e49f264322d3abfc2828fbc311b6cdf67ae8"
},
{
"name": "abc",
"unicode": "1F524",
- "digest": "652a2381a7b587d8a52d5178e2d7d6c8600b33d36160fa69677943da374105bc"
+ "digest": "282c817ee3414d77a74b815962c33dd9fe71fabaea8c7a9cec466100fbe32187"
},
{
"name": "abcd",
"unicode": "1F521",
- "digest": "35ade4fd3d75294ebb72c24490aa32745604edc6cabe095b90634cd3ce78c07b"
+ "digest": "686728c759f4683c64762ee4eda0a91bf2041f0ae4f358aacf6c09bf51892eff"
},
{
"name": "accept",
"unicode": "1F251",
- "digest": "8212ed158cc447c92813273fc915e84d3d5c4c48d1b38e498c088bad27ab8145"
+ "digest": "7208d34c761f10a7fd28f98e25535eba13ff91a64442fc282a98bb77722614f1"
},
{
"name": "aerial_tramway",
"unicode": "1F6A1",
- "digest": "8039d7f67e6e5b211066cab6cf2142afc3aca5c830a357369362c9b484029563"
+ "digest": "98df666f34370fc34ce280d84bba5a7e617f733fbbfe66caa424b2afa6ab6777"
},
{
"name": "airplane",
"unicode": "2708",
- "digest": "18f4dfac323555d8cdabb79148874c0185ce98e1a08e69414d236b23e502a854"
+ "digest": "cc12cf259ef88e57717620cd2bd5aa6a02a8631ee532a3bde24bee78edc5de33"
},
{
"name": "airplane_arriving",
"unicode": "1F6EC",
- "digest": "9a1c81d97512e5d0e3acec40290d00f616ec182140909859e366a734b9f840bb"
+ "digest": "80d5b4675f91c4cff06d146d795a065b0ce2a74557df4d9e3314e3d3b5c4ae82"
},
{
"name": "airplane_departure",
"unicode": "1F6EB",
- "digest": "e3c5ff4038db998c1897cb237d0b865da0bc60331c758f204e45a979d5fab445"
+ "digest": "5544eace06b8e1b6ea91940e893e013d33d6b166e14e6d128a87f2cd2de88332"
},
{
"name": "airplane_northeast",
@@ -72,12 +72,12 @@
{
"name": "airplane_small",
"unicode": "1F6E9",
- "digest": "f98b44422d6bf505b50330805ecf68013d035341f0b6487c3c05ad913eb5abd3"
+ "digest": "1a2e07abbbe90d05cee7ff8dd52f443d595ccb38959f3089fe016b77e5d6de7d"
},
{
"name": "small_airplane",
"unicode": "1F6E9",
- "digest": "f98b44422d6bf505b50330805ecf68013d035341f0b6487c3c05ad913eb5abd3"
+ "digest": "1a2e07abbbe90d05cee7ff8dd52f443d595ccb38959f3089fe016b77e5d6de7d"
},
{
"name": "airplane_small_up",
@@ -102,67 +102,67 @@
{
"name": "alarm_clock",
"unicode": "23F0",
- "digest": "84ddd7b3b857c165410b7b44863e5354ca0f3591c3bfe56231f12c9f7531a96f"
+ "digest": "fef05a3cd1cddbeca4de8091b94bddb93790b03fa213da86c0eec420f8c49599"
},
{
"name": "alembic",
"unicode": "2697",
- "digest": "45698914a21683f06931d807af171bcb6984e5ebce66012bba71b467565bd69d"
+ "digest": "c94b2a4bf24ccf4db27a22c9725cfe900f4a99ec49ef2411d67952bcb2ca1bfb"
},
{
"name": "alien",
"unicode": "1F47D",
- "digest": "94dbe4e90614c654145aba93610c43e3ab86df8ca07391bd4e56383f9329c008"
+ "digest": "856ba98202b244c13a5ee3014a6f7ad592d8c119a30d79e4fc790b74b0e321f7"
},
{
"name": "ambulance",
"unicode": "1F691",
- "digest": "82ef36bcd13c88a4b2397c918b8048adc6bf045ed2532ff568e0dfd1b1b29c3c"
+ "digest": "d9b3c1873de496a4554e715342c72290fb69a9c6766d7885f38bfe9491d052da"
},
{
"name": "amphora",
"unicode": "1F3FA",
- "digest": "d3758d88aa1fc3be01894102f57479d3a49790510d38ad3d06a2774962010608"
+ "digest": "4015f907b649b5e348502cc0e3685ed184e180dca5cc81c43ec516e14df127bf"
},
{
"name": "anchor",
"unicode": "2693",
- "digest": "27c6034f769d9f020362fc5b227b9279651cc940861e727d1f6ccd59af98f851"
+ "digest": "2b29b34ef896ebab70016301e3d1880209bbc3c5a5b8d832e43afff9b17ad792"
},
{
"name": "angel",
"unicode": "1F47C",
- "digest": "c1b8ad2adc7686e7fbbe4ec357071e7228a5e0762e001bb589e2f97ff258d5c7"
+ "digest": "db75c2460aaf9cd07cb41fe22c8a6079f3667ffe612a71611358720e2b5512a4"
},
{
"name": "angel_tone1",
"unicode": "1F47C-1F3FB",
- "digest": "90b701c43311b1096c4a012d9905a186f1a16829ea2707921a8418c28617d751"
+ "digest": "5871a622469b96296365adaf77d83167759692124c20e5a6e062a525af33472a"
},
{
"name": "angel_tone2",
"unicode": "1F47C-1F3FC",
- "digest": "d6bcaf1b76e25d486d4ab9b159cf727782d508543d1ae27c8d2c12d2f13d6eb0"
+ "digest": "f5993198a5d9daf39e761c783461f07bca237f4e9b739ac300bb8ca001a69a1a"
},
{
"name": "angel_tone3",
"unicode": "1F47C-1F3FD",
- "digest": "3069285e6218c8083cb0085aa10017bcdea033e321d97ba339a84892074b903a"
+ "digest": "f0c97a7c4354626267d6ab0f388e4297ad255ab9b061f9c68fbcaa0abfc52783"
},
{
"name": "angel_tone4",
"unicode": "1F47C-1F3FE",
- "digest": "dbb87019752d9caa94ce086858c1e3225b62e221ad599f5106548fda2456fc2b"
+ "digest": "6e5dc724c1939d1b0d1a91343662b5bd61ced7709c97802977145ffab6a1f7ac"
},
{
"name": "angel_tone5",
"unicode": "1F47C-1F3FF",
- "digest": "f77703df97720c27a128b5f3c0948b9e04a6b6b81ea5306468154f9bf56225db"
+ "digest": "52186e1de350c27d25d6010edf44f64a30338b65912ca178429fbcfbd88113c2"
},
{
"name": "anger",
"unicode": "1F4A2",
- "digest": "2253b7ff0894f247bc6f04d841a748c56d6c94684880c13df42387691ff20e75"
+ "digest": "332493913891aa0eda2743b4bb16c4682400f249998bf34eb292246c9009e17f"
},
{
"name": "anger_left",
@@ -177,152 +177,152 @@
{
"name": "anger_right",
"unicode": "1F5EF",
- "digest": "24b572d64c519251a3ae8844e8d66fd6955752aff99aebe7dc20179505a466c4"
+ "digest": "8b049511ef3b1b28325841e2f87c60773eaf2f65cabba58d8b0ec3de9b10c0ae"
},
{
"name": "right_anger_bubble",
"unicode": "1F5EF",
- "digest": "24b572d64c519251a3ae8844e8d66fd6955752aff99aebe7dc20179505a466c4"
+ "digest": "8b049511ef3b1b28325841e2f87c60773eaf2f65cabba58d8b0ec3de9b10c0ae"
},
{
"name": "angry",
"unicode": "1F620",
- "digest": "c4188ba70df99d8ccef5706d711176725d3dd50d62f065a177d68d85c7828107"
+ "digest": "7e09e7e821f511606341fb5ce4011a8ed9809766ab86b7983ffa6ea352b39ec1"
},
{
"name": "anguished",
"unicode": "1F627",
- "digest": "9c2347308133ae50dc04da62042fff847f4c477b2956b8aa976f0413899e38bc"
+ "digest": "a2b6f052996969a17150249d9ef5db742da3d6585bd38ca61eb14c4c13cda54f"
},
{
"name": "ant",
"unicode": "1F41C",
- "digest": "d2af2ed1cfe15d649aa329d965764a1e8726941d833841781a5b66d7dd0b0921"
+ "digest": "929abeaff7ba21ab71cd1ab798af7a6b611e3b3ce1af80cede09a116b223e442"
},
{
"name": "apple",
"unicode": "1F34E",
- "digest": "a9babee24f454934a5e1fb8d781cbce354dfd88e8a8e01f02e8b30071fd40460"
+ "digest": "2a1b85ce57e3d236ae7777dcf332ec37d03bfd7b19806521a353bc532083224d"
},
{
"name": "aquarius",
"unicode": "2652",
- "digest": "1a168c252678847d1f9ef450887489e3bdc207ecae4b6fb05e92295ff861ae2c"
+ "digest": "fdc42cd41b0dace5eae6baba3143f1e40295d48a29e7103a5bba1d84a056c39d"
},
{
"name": "aries",
"unicode": "2648",
- "digest": "bde262a8795e12f8b0ebb3f0f8c3a56104062fcee8d5d678cf4bb445a7daf698"
+ "digest": "deb135debcde0a98f40361a84ab64d57c18b5b445cd2f4199e8936f052899737"
},
{
"name": "arrow_backward",
"unicode": "25C0",
- "digest": "ddae36d1febf5c246e51d599e2898a8aa30cd47f88b5bcb469e3ca9d22538b97"
+ "digest": "e162ac82e90d1e925d479fa5c45b9340e0a53287be04e43cbbb2a89c7e7e45e4"
},
{
"name": "arrow_double_down",
"unicode": "23EC",
- "digest": "906f42b5f788128ed90d2d162cf03e6e595a50ad05e0aa5f64e925637379d0cd"
+ "digest": "03ca890b05338d40972c7a056d672df620a203c6ca52ff3ff530f1a710905507"
},
{
"name": "arrow_double_up",
"unicode": "23EB",
- "digest": "2129a57402980de6fc6f59ad8354525c2dbcd66d1b78f4de091181ddc81e0693"
+ "digest": "e753f05bce993d62d5dc79e33c441ced059381b6ce21fa3ea4200f1b3236e59d"
},
{
"name": "arrow_down",
"unicode": "2B07",
- "digest": "370e4f41565d5dab245c20e45c502505a56d26c2392283781b841eb3e905edb2"
+ "digest": "9bf1bd2ea652ca9321087de58c7a112ea04c35676a6ee0766154183f8b95af6c"
},
{
"name": "arrow_down_small",
"unicode": "1F53D",
- "digest": "98a2b183f2daec425160bbfce1d2b940b8baa0d5032fdacfa9453e39bed5651b"
+ "digest": "7766198bc60cf59d6cdaeeaa700c2282bfff2f0fdeb22cf4581ca284b87a3bb7"
},
{
"name": "arrow_forward",
"unicode": "25B6",
- "digest": "348627b8e0f55cf1e9ab19c9de1d170371b2c4cb4dda9a2aa8e0c558db08b18a"
+ "digest": "db77d9accd1e02224f5d612f79cd691e6befdf22063475204836be6572510fb7"
},
{
"name": "arrow_heading_down",
"unicode": "2935",
- "digest": "96c64953fc3134711247bef320f252c48993ebc90494925b7fee42ffce2a2ec2"
+ "digest": "f5396069c8f63c13e6c3e0ecd34267c932451309ade9c1171d410563153bf909"
},
{
"name": "arrow_heading_up",
"unicode": "2934",
- "digest": "94f94e74176cc050703b3584f3f700debf86e4e61b893a441825a21fa3f8ce74"
+ "digest": "1cad71923fa3df24cf543cae4ce775b0f74936f2edd685fd86a7525c41a14568"
},
{
"name": "arrow_left",
"unicode": "2B05",
- "digest": "4553be62a63d7550deac4f7dbeffce6006f769ae6cddfb8c795671672011ba0b"
+ "digest": "b629bb3dbe161ef89cfcfced0c7968a68e44a019ad509132987e4973bdc874e7"
},
{
"name": "arrow_lower_left",
"unicode": "2199",
- "digest": "10f83c252110d705cdcfebc35a70c341ad288730d0c0729479e3a96e263d5120"
+ "digest": "879136ba0e24e6bf3be70118abcb716d71bd74f7b62347bc052b6533c0ea534d"
},
{
"name": "arrow_lower_right",
"unicode": "2198",
- "digest": "ee33abd4c96c19e9b80a2fc1500ba8ecaa6668c49310cc816a496e8c61af3850"
+ "digest": "86d52ac9b961991e3aaa6a9f9b5ace4db6ffd1b5c171c09c23b516473b55066d"
},
{
"name": "arrow_right",
"unicode": "27A1",
- "digest": "2611e9138a2651916f414015d0287f5f0af266514d96a42915d32b04fb652a90"
+ "digest": "45f26a1cbb0f00ed3609b39da52e9d9e896a77e361c4c8036b1bf8038171bd49"
},
{
"name": "arrow_right_hook",
"unicode": "21AA",
- "digest": "628b06384a2963a4fe81e9fbf4e22511f697878d9b9db7d2fc98f8aadbe8f4f9"
+ "digest": "4f452679c71bcea4fc4a701c55156fef3ddc1ebbc70570bedfc9d3a029637ab1"
},
{
"name": "arrow_up",
"unicode": "2B06",
- "digest": "c09e5f41c01028b45707c525d30d3d6731ec57b7447f0d7ba4ad6c1404449e5c"
+ "digest": "982b988ef6651d8a71867ba7c87f640f62dd0eeb0b7c358f5a5c37e8fe507b8b"
},
{
"name": "arrow_up_down",
"unicode": "2195",
- "digest": "e7fd92d24a01702f76c7fcc0de998bc81fbfb93711d076984f6da91d1dccd84c"
+ "digest": "645ed8fb6646f49bfd95af1752336deacdadbe5cba13904023a704288f3b0e2c"
},
{
"name": "arrow_up_small",
"unicode": "1F53C",
- "digest": "bc48dad74bc1d0c5579cbf5e3d005314b0d21bc5b5ebbba2b05136e33f49296d"
+ "digest": "4a8c5789c13a852517e639e7a62c2d331464e6fb0358985aa97c1515e97b5e8b"
},
{
"name": "arrow_upper_left",
"unicode": "2196",
- "digest": "792a9709f03843024e53d201cb4769c59b656c3bf0dff2306e8e605493a66b93"
+ "digest": "79026f828d6ceb7c55a9542770962ba6dcd08203995f6ceeb70333a12307d376"
},
{
"name": "arrow_upper_right",
"unicode": "2197",
- "digest": "ee934b0c9cff270efd30a6cafc15253d405efd2c93b4785ac2ed4ea6420266a6"
+ "digest": "7e0f33dfbe65628991c170130d366a3e2cedaf8862ddfcaf3960f395d3da1926"
},
{
"name": "arrows_clockwise",
"unicode": "1F503",
- "digest": "914f4120513730d7a19c9f8c4e59223a90568de0b25a225b712b31fa9697ef4f"
+ "digest": "88669679977f7157f0acaa9d6a1b77ccf84d25eb78c5bc8afcde38d3635e7144"
},
{
"name": "arrows_counterclockwise",
"unicode": "1F504",
- "digest": "86d87597e4e3db6dbba9907ee82412db0cbab1ea875bd0be6505dd886dc19b90"
+ "digest": "a2c6a6d3643c128aee3304cd03bb3d7cfe4d35d3ba825bc9c1142d7832b4426e"
},
{
"name": "art",
"unicode": "1F3A8",
- "digest": "dfc6b0da780199df86507d65b0499ba1706c266ae7badcb0e7fb5b85af7c9578"
+ "digest": "b6bc6c4bfb594aadcbb641d006031867678504764bbe0ab84e7b08567a9498da"
},
{
"name": "articulated_lorry",
"unicode": "1F69B",
- "digest": "4c4de240ebd175f7b53453eda4e51f2e57d0db2a98d317f804116e14e47cff1d"
+ "digest": "c115e6613ebd718268aa31d265e017138b9fb58bbb8201eb3f40de2380e460aa"
},
{
"name": "ascending_notes",
@@ -332,117 +332,117 @@
{
"name": "asterisk",
"unicode": "002A-20E3",
- "digest": "0b7f27f545b616677c83d40ff957337477b2881459b4d3c839ae55e23797419f"
+ "digest": "33d92093f2914448d5a939cf62e8ee3e32931923abdef5f0210e8a8150fa312d"
},
{
"name": "keycap_asterisk",
"unicode": "002A-20E3",
- "digest": "0b7f27f545b616677c83d40ff957337477b2881459b4d3c839ae55e23797419f"
+ "digest": "33d92093f2914448d5a939cf62e8ee3e32931923abdef5f0210e8a8150fa312d"
},
{
"name": "astonished",
"unicode": "1F632",
- "digest": "58632b97e274ade5183752db2b3c5c4fe29effcd5a9720a8d01fa809b97023dc"
+ "digest": "f8531bdda5070d10492709085f4ff652b8be9be6458758940358b9fc594a1f14"
},
{
"name": "athletic_shoe",
"unicode": "1F45F",
- "digest": "1fc55d85a4d6751f9e60467801b051d2fb3341bdcc33b8d3695d5143359edb43"
+ "digest": "1f90dc390e0dea679085465b7f9e786dfd7dd56a3b219987144ed37ab1e9bf95"
},
{
"name": "atm",
"unicode": "1F3E7",
- "digest": "bf827ef6c349f5b6912d821457975a4720d1750529d907e94ece429b7a388d7e"
+ "digest": "7d3ce6a6afb4951546883404b8e36904179f88f1aa533706cf7bf0bbe0d6fd3c"
},
{
"name": "atom",
"unicode": "269B",
- "digest": "cbce1725602efbb77a935cfae5407e4d75489ee988910296c7f6140665afc669"
+ "digest": "6b6bb83b00707a314e46ff8eefbda40978a291ec7881caba1b1ee273f49c1368"
},
{
"name": "atom_symbol",
"unicode": "269B",
- "digest": "cbce1725602efbb77a935cfae5407e4d75489ee988910296c7f6140665afc669"
+ "digest": "6b6bb83b00707a314e46ff8eefbda40978a291ec7881caba1b1ee273f49c1368"
},
{
"name": "b",
"unicode": "1F171",
- "digest": "9116256b3189977e37f6da7ddedf82bb29b0358829a4e8718fd59e51d9b86b3c"
+ "digest": "722f9db9442e7c0fc0d0ac0f5291fbf47c6a0ac4d8abd42e97957da705fb82bf"
},
{
"name": "baby",
"unicode": "1F476",
- "digest": "66596bea11015154e0b1752b85f349f4286c6643ee6f51ee5e60e0d625c4ae9a"
+ "digest": "219ae5a571aaf90c060956cd1c56dcc27708c827cecdca3ba1122058a3c4847b"
},
{
"name": "baby_bottle",
"unicode": "1F37C",
- "digest": "ed42994b4a539b8bfeccde0f3c7e9c7f54d6696ff48ce7e48171bbab51002348"
+ "digest": "4fb71689e9d634e8d1699cf454a71e43f2b5b1a5dbab0bf186626934fdf5b782"
},
{
"name": "baby_chick",
"unicode": "1F424",
- "digest": "ea2cfa0e5c2cbff5fffdb52cc04dfe7872834bd7cfeaa45e0541b8faffcbd0e9"
+ "digest": "14119874e9b5548028dfb9cc593a541efc1d075ac839a565b92e0c3253cffe7e"
},
{
"name": "baby_symbol",
"unicode": "1F6BC",
- "digest": "65df04dff8739b86f7663ae9c0648927341f360a986655e109721b0e16013b75"
+ "digest": "fb4db66868cda45ea3879ffc2ff4f763c56d2d889ae0ab17fe171129ede02f98"
},
{
"name": "baby_tone1",
"unicode": "1F476-1F3FB",
- "digest": "bc747527a2d723cf99ef3fc2539c19d29634c92ff417736982d3bf87d65d06eb"
+ "digest": "cd3faf223a298c34e05d469d9d0db08438d97df7fd82c0973f8a9e07d553f5b1"
},
{
"name": "baby_tone2",
"unicode": "1F476-1F3FC",
- "digest": "b82bba7a666b7d070751726e54acc7fb8f96e2dfc09e9610d61cfd20947aef9c"
+ "digest": "5b4539e22e0dd726c27eb8af2357f9240a52aed3f710f3234571cff029cc6198"
},
{
"name": "baby_tone3",
"unicode": "1F476-1F3FD",
- "digest": "7f45dfd4ea2ae8515d419ffa13e7ee5c625b024b4e521ace5344c414bb929da0"
+ "digest": "720e740e1ac63c6372269132b1fb6e07a6b91f5c808cc3adef59f0b4500e5e72"
},
{
"name": "baby_tone4",
"unicode": "1F476-1F3FE",
- "digest": "80b1854626616f15426649cc6415e4911a55c8f761422fe48a08af9e8ac6a7cb"
+ "digest": "5e43b69c509bd526ad6f081764578c30b6f3285fb7442222e05ccf62e53bfb64"
},
{
"name": "baby_tone5",
"unicode": "1F476-1F3FF",
- "digest": "9f890804d19a61bee76a29644c818045dd96cf69d67cfbca2d11f4ad376b27da"
+ "digest": "85bba6e0940ccfb99999fe124e815f9dd340d00a5568e13967b02245a62dbf54"
},
{
"name": "back",
"unicode": "1F519",
- "digest": "1dc73947b8f56e033777ca3f747407923bd16b07e53a6c78b09950ca474b7e7a"
+ "digest": "083e4e48b51092c28efb4532e840e1091b5d4b685c6e0f221aa0228f061cd91e"
},
{
"name": "badminton",
"unicode": "1F3F8",
- "digest": "3f95180c1175d0248ebf4b8650cf86566c39e0486d828078244080194c14d4fe"
+ "digest": "353eb7ee93decd9fe0072e4d78a5618d5e2d9e77a6e4de9fe171870d75e02a66"
},
{
"name": "baggage_claim",
"unicode": "1F6C4",
- "digest": "7c1a69511aa2a93984d601da4d1cef1cb4cefbbf127b1486278da8c01345bbf3"
+ "digest": "7d6bceca92c266da6d2b91dfcf244546fc11022e039e7da8e6888c1696bb2186"
},
{
"name": "balloon",
"unicode": "1F388",
- "digest": "a10c2b0865179cdbdef339494ec9b2a109451a356e53738d6a9dd43232500956"
+ "digest": "65760aedc1503b426927cff78c24449d563843a274961d962718fa9638375d54"
},
{
"name": "ballot_box",
"unicode": "1F5F3",
- "digest": "0455ea75612efe78354315b4c345953d2d559bb471d5b01c1adc1d6b74ed693a"
+ "digest": "4175a56eca5c6458574a681e109b1403fbb143cf27f69ae6c1917650f3e08892"
},
{
"name": "ballot_box_with_ballot",
"unicode": "1F5F3",
- "digest": "0455ea75612efe78354315b4c345953d2d559bb471d5b01c1adc1d6b74ed693a"
+ "digest": "4175a56eca5c6458574a681e109b1403fbb143cf27f69ae6c1917650f3e08892"
},
{
"name": "ballot_box_check",
@@ -457,7 +457,7 @@
{
"name": "ballot_box_with_check",
"unicode": "2611",
- "digest": "5f5cec7fe462557d31e8d2b836534c1e76d546cc0061236fa2af3667972b84aa"
+ "digest": "c98d6f3588dd87e2f318bbfe6c646399a905450edfd814edae4e5b1bddef2134"
},
{
"name": "ballot_box_x",
@@ -482,277 +482,277 @@
{
"name": "bamboo",
"unicode": "1F38D",
- "digest": "feb0cf2f1012a1c0649b8c66f7e96e2d8bcdefe879c5a52dab3e25c51009e3b2"
+ "digest": "e4ee65088df43d7081b1ce6fd996f66f3e0accd88840855c47a98a22997823dd"
},
{
"name": "banana",
"unicode": "1F34C",
- "digest": "aa9a1e6db00efa94a7f414c570eff7fc29011be64031a24d03b7f37b617cfd2d"
+ "digest": "f9e8ff910c282c20a8907ff64926b5de4ee250529a1ed718fb33302e6fff8dd9"
},
{
"name": "bangbang",
"unicode": "203C",
- "digest": "bdd350766ccd1c0138f6294f7ebfa3e9867b02bda40a743f7062e52c68358765"
+ "digest": "76536fee63fe964a3f3839d309b1f45028fb0c43f4d1eeee495f17e1532b4def"
},
{
"name": "bank",
"unicode": "1F3E6",
- "digest": "c9648c93049cf8e7884242e58ae3145383d2e5034c9090e0d34c53f5bbce397f"
+ "digest": "f5d2976bf6d521638ccacc74be06bd4abfeab06c5d898a9d245edad45a5b6306"
},
{
"name": "bar_chart",
"unicode": "1F4CA",
- "digest": "942277f72a5b754b13454dab62c85b1ff3447544f38ec76a285f3be32f6f5d12"
+ "digest": "65a328a1b2d7a5332dd4d93f4dbca13d976f0a505b00835c3fc458e394804240"
},
{
"name": "barber",
"unicode": "1F488",
- "digest": "e1526eea685aafc56fb83d07f8ff63c9967600e447b0e5f831a17d6153f2062d"
+ "digest": "5e8053d3bb3765a8632fd1cbfe21163f74ed79f6be377eb9603eaaf883d8dc46"
},
{
"name": "baseball",
"unicode": "26BE",
- "digest": "3d028b16a898f3a15874bc9d3891f9fbf59ea1c226c5c774eddb58a712c489ae"
+ "digest": "46ac16f8b5455b942f6dbff9483a6fd277721e6719d2731573baabd21c44b34f"
},
{
"name": "basketball",
"unicode": "1F3C0",
- "digest": "b2f5a3904d505db066337a24fc840ef75b49ef4c5f152227d8e632ff82285b12"
+ "digest": "cc83e2aea8fcd2e9a5789e1932ee3766c40843c142fd3565c4e77dafb21ec7d7"
},
{
"name": "basketball_player",
"unicode": "26F9",
- "digest": "e94beb69f631667479a80095bf313ceb3aa109d6ebb80f182722360a6d2a214e"
+ "digest": "793ba53c95e8def769383b612037bc9b9bceecaf1e0430c50a4cc128ad18d9b9"
},
{
"name": "person_with_ball",
"unicode": "26F9",
- "digest": "e94beb69f631667479a80095bf313ceb3aa109d6ebb80f182722360a6d2a214e"
+ "digest": "793ba53c95e8def769383b612037bc9b9bceecaf1e0430c50a4cc128ad18d9b9"
},
{
"name": "basketball_player_tone1",
"unicode": "26F9-1F3FB",
- "digest": "6fc77cf2f26ee18e9a3faea500d4277839f77633f31ee618a68c301f1ad32d90"
+ "digest": "2a06522b971e68ee5b8777a58253009b548f4da2fb723c638acb3d7b04edba8f"
},
{
"name": "person_with_ball_tone1",
"unicode": "26F9-1F3FB",
- "digest": "6fc77cf2f26ee18e9a3faea500d4277839f77633f31ee618a68c301f1ad32d90"
+ "digest": "2a06522b971e68ee5b8777a58253009b548f4da2fb723c638acb3d7b04edba8f"
},
{
"name": "basketball_player_tone2",
"unicode": "26F9-1F3FC",
- "digest": "6ee9060c24d92708e12a854fb0bdf5c717c90b8c0350d8aa40c278b41bfa12fc"
+ "digest": "ecc0e44ab9bc478ba45a055fd69a3a38377b917aac5047963fe80ff8ae5fd8e3"
},
{
"name": "person_with_ball_tone2",
"unicode": "26F9-1F3FC",
- "digest": "6ee9060c24d92708e12a854fb0bdf5c717c90b8c0350d8aa40c278b41bfa12fc"
+ "digest": "ecc0e44ab9bc478ba45a055fd69a3a38377b917aac5047963fe80ff8ae5fd8e3"
},
{
"name": "basketball_player_tone3",
"unicode": "26F9-1F3FD",
- "digest": "752e90dbfa7c7a9ae3f37de924e22f3c3d5a7e54dd41c8e8eb99cabb0dad73cf"
+ "digest": "2d38f1851c685d29532c042461d7b5b996e5f04f0ed54857c66073c62a99ceac"
},
{
"name": "person_with_ball_tone3",
"unicode": "26F9-1F3FD",
- "digest": "752e90dbfa7c7a9ae3f37de924e22f3c3d5a7e54dd41c8e8eb99cabb0dad73cf"
+ "digest": "2d38f1851c685d29532c042461d7b5b996e5f04f0ed54857c66073c62a99ceac"
},
{
"name": "basketball_player_tone4",
"unicode": "26F9-1F3FE",
- "digest": "38bedc3074e6243454d568d9b665f5764f1a3d983875651ce7a1cdb53da9f6c8"
+ "digest": "09e957c6e9ffc196415f28073aa261feba8efba0bdc694dc08f8f7cd1f88f720"
},
{
"name": "person_with_ball_tone4",
"unicode": "26F9-1F3FE",
- "digest": "38bedc3074e6243454d568d9b665f5764f1a3d983875651ce7a1cdb53da9f6c8"
+ "digest": "09e957c6e9ffc196415f28073aa261feba8efba0bdc694dc08f8f7cd1f88f720"
},
{
"name": "basketball_player_tone5",
"unicode": "26F9-1F3FF",
- "digest": "25ee1e84670d3db96d3ad098c859abd6b3448f55f668ce0c195ee2337a215de7"
+ "digest": "c631cefc5d2a0a31bdb9f0a0d97ea68b1c6928e565468998403034644572a0b0"
},
{
"name": "person_with_ball_tone5",
"unicode": "26F9-1F3FF",
- "digest": "25ee1e84670d3db96d3ad098c859abd6b3448f55f668ce0c195ee2337a215de7"
+ "digest": "c631cefc5d2a0a31bdb9f0a0d97ea68b1c6928e565468998403034644572a0b0"
},
{
"name": "bath",
"unicode": "1F6C0",
- "digest": "ae6301a6354630cd9dc06a5137f23f826d019c8298b2b012b6ff31b773a910b6"
+ "digest": "33b371832f90aad50baf5296f3ad4cc081c319b279f989c74409903d8568e917"
},
{
"name": "bath_tone1",
"unicode": "1F6C0-1F3FB",
- "digest": "fce7ae2e7ef3f7f44f36c2ad49348b4cf7fce0b0c17e1a90a1e85734cee95b2a"
+ "digest": "7ae2989e47788ba71359d52da68feec95aaff68a77d5a6556957df1617af8536"
},
{
"name": "bath_tone2",
"unicode": "1F6C0-1F3FC",
- "digest": "4d1c9444f16467488fe939fdad279d6855d28be564e5dcc1990451c4b9ae8c95"
+ "digest": "2e86f8edad54d15a7094cd52160cbe51d10aa1750cfb0b3b58e93533f070e327"
},
{
"name": "bath_tone3",
"unicode": "1F6C0-1F3FD",
- "digest": "9a59a4360effb48af4cbb1a953655ef61e69375407038b4d0bd8068fbaf3cc16"
+ "digest": "654c0cd083a67ff330a38d07352876d265390e5399e5352598d64a6c7e5eeba7"
},
{
"name": "bath_tone4",
"unicode": "1F6C0-1F3FE",
- "digest": "01aafa8a53a08018b9fbf28ec6b3b918d6bd0dee7a891196f32f81f60d114f0e"
+ "digest": "adad88c6830f31c4b5be194d1987d6aadf4adf45e4cb7f2e4657f0d20c0d663a"
},
{
"name": "bath_tone5",
"unicode": "1F6C0-1F3FF",
- "digest": "2733e81ccaee21231c2e47e3310b431e9bd784bf34f0db609f8eadcee359500d"
+ "digest": "952c4c9bf24e001e23a33ebf97bd92969cd9143e28ce93f9aafc708a8f966903"
},
{
"name": "bathtub",
"unicode": "1F6C1",
- "digest": "9515e3bb9ab41350305e64fc6877aae82d51e1ba8ce8b2b4b8ffaeda960820cd"
+ "digest": "844dffb87ef872594195069b0d0df27c3fe51f3967ccbc8b2df811a086dd483a"
},
{
"name": "battery",
"unicode": "1F50B",
- "digest": "7d4d475c1d5b1be55c319953e3363ff864fe4fcd921a8aa649b9a547c0894deb"
+ "digest": "949ae06648667fb13d9121a6dfdd03bf8692794b28c36e9a8e8ac4515664449a"
},
{
"name": "beach",
"unicode": "1F3D6",
- "digest": "52855d75cfa4476ccc23c58b4afcb76ee48abb22a9a6081210c8accefdf33099"
+ "digest": "37fa2158977d470186caaa1aa06669b6dc5026ba49a0c44c5255541f8e974e26"
},
{
"name": "beach_with_umbrella",
"unicode": "1F3D6",
- "digest": "52855d75cfa4476ccc23c58b4afcb76ee48abb22a9a6081210c8accefdf33099"
+ "digest": "37fa2158977d470186caaa1aa06669b6dc5026ba49a0c44c5255541f8e974e26"
},
{
"name": "beach_umbrella",
"unicode": "26F1",
- "digest": "cefe8e195d21d3e0769d3bfe15170db9e57c86db9d31cacb19fcdc8d2191b661"
+ "digest": "d045f1de10038b9fb1eaa2529b2f80b7e3be1cff503efcc2d680663d1fbbc18f"
},
{
"name": "umbrella_on_ground",
"unicode": "26F1",
- "digest": "cefe8e195d21d3e0769d3bfe15170db9e57c86db9d31cacb19fcdc8d2191b661"
+ "digest": "d045f1de10038b9fb1eaa2529b2f80b7e3be1cff503efcc2d680663d1fbbc18f"
},
{
"name": "bear",
"unicode": "1F43B",
- "digest": "b5ac126875c20c82b9e3140b143233944a2e4132d781d0b575e83673988523cb"
+ "digest": "a4b9066eaa5681e6af06e596a96a5217037460ffc3b013e8db4d34d762413246"
},
{
"name": "bed",
"unicode": "1F6CF",
- "digest": "1919245d7a76799aad0533eb72db2cbaa1f32ee8231a0c1989d3f233f2d42370"
+ "digest": "08f6e20db51b1fb650b390a0a3074938646772f3fcee8c295d47742e44fe1e30"
},
{
"name": "bee",
"unicode": "1F41D",
- "digest": "69ada63403c8dabae39c63ba143143aeb59b66faae6aa82d8342337925a9e6b5"
+ "digest": "5beb9a1650681b4adf69999d4808231c38f41a3ec693480b807cda86f964c570"
},
{
"name": "beer",
"unicode": "1F37A",
- "digest": "b71dd6efdb4ce7d9d71fdbf82a2ccf83841fb0cceb119ee7da1e575d3bfa853c"
+ "digest": "69e227104976548ee0f37375fe1526fd65ef0a328d2d92db2feb1edfd7032bd4"
},
{
"name": "beers",
"unicode": "1F37B",
- "digest": "994108cebfe0c614c05967af4e3864d8adbbfcf7cccef1cbd42a47b7dfabf80c"
+ "digest": "db8b32d93bf6d161a3b027e55651d8f51231b13928b3610987ef62bb634d7501"
},
{
"name": "beetle",
"unicode": "1F41E",
- "digest": "ec351ce238a81711eef00e5be1de2e198423cf524b60e531d435902b44420edc"
+ "digest": "5aaa428e3f63f7cd1696839ab05be03fa0cd0cbed30a05c36cb270da330c3849"
},
{
"name": "beginner",
"unicode": "1F530",
- "digest": "13288d9fc221dc02f4181b998104e13c3c5c98d3c4e650186bef59a46d39f6f0"
+ "digest": "2de4fdf92f182c42b12b7527034eaf767d996848b61f31ee69167728411ca0b1"
},
{
"name": "bell",
"unicode": "1F514",
- "digest": "784b9a82814ce14a264e54b3a8f8e706f3c7b763646d9f8174c4aa84ad41ef09"
+ "digest": "18d419417746ead408072b78fe2edb6314cdb49492873966fa9f9f06be09899b"
},
{
"name": "bellhop",
"unicode": "1F6CE",
- "digest": "c15455f1b52ac26404b5c13a0e1070212ed1830026422873f4f6335e26e31259"
+ "digest": "b8187bc4059f6a0924a47fe3f6c07f656bed0334bbcbfa1e89f800fe6594ff08"
},
{
"name": "bellhop_bell",
"unicode": "1F6CE",
- "digest": "c15455f1b52ac26404b5c13a0e1070212ed1830026422873f4f6335e26e31259"
+ "digest": "b8187bc4059f6a0924a47fe3f6c07f656bed0334bbcbfa1e89f800fe6594ff08"
},
{
"name": "bento",
"unicode": "1F371",
- "digest": "d59314b17a8646d4a78fefb7b79f289f33d4aaea893fed4cad0b890df63395e7"
+ "digest": "d46d4f681c5da7f7678b51be3445454a8ed18d917e132ae79077f05310e485f1"
},
{
"name": "bicyclist",
"unicode": "1F6B4",
- "digest": "e7359d615d40325bb08a145cfebde2ecef448deeb21695a34b55d3ccb971447f"
+ "digest": "3302147b6b47c16adb97d78b7b761a1ca80e6d0b41d0b60f4da338d2f55f968b"
},
{
"name": "bicyclist_tone1",
"unicode": "1F6B4-1F3FB",
- "digest": "e45808faa32f4ffb881d3569c0b8e2c69d4a64665f4d1fae24d7a1e5f1d3ea4b"
+ "digest": "27eaae0eb61f5e7b3cd9faf02c042d6643a368051a7c9d7da4e0fb9802d39242"
},
{
"name": "bicyclist_tone2",
"unicode": "1F6B4-1F3FC",
- "digest": "92a3494270d1da6a117e92402c7898d4a7fffbe3d6143fb9ae445c4827c0c8a4"
+ "digest": "39ee9e1071700da7079ad0146bf5711c3a222991eeca8b29b72a65677604444d"
},
{
"name": "bicyclist_tone3",
"unicode": "1F6B4-1F3FD",
- "digest": "6fdf1db2bbd08d06b643b08f0f29daeaa20e0b8c8abec21132191f435cc05e42"
+ "digest": "03e1d2c4232c896147a9d4bf43becd61edbb5c84fc7193ecea474c0f9fb36817"
},
{
"name": "bicyclist_tone4",
"unicode": "1F6B4-1F3FE",
- "digest": "d9c27848e1bcc8197c858e1ef12a537f4ed6c77fb211b6731388dc88c2bb7a61"
+ "digest": "61393d9c4805be0379d86dd5bec9a1b02314433ab36cfd85bb48dfd073746617"
},
{
"name": "bicyclist_tone5",
"unicode": "1F6B4-1F3FF",
- "digest": "4892af1a8a0229a813d7b8e3d88481c2365e3e1a5ce2e0e27ce432c5336da810"
+ "digest": "2b46d5f8303e5710dbf5db3a4edc9d88a032fe123fe79158024c9f51df5458c6"
},
{
"name": "bike",
"unicode": "1F6B2",
- "digest": "e726f97b5432f46ed51328c0930d1d63b3a2d7b67c5c2303a5ca997083cfcac1"
+ "digest": "b41daa7c549d483e2336186a28baaa8ecb11986f490c0c54c793c44900c8f652"
},
{
"name": "bikini",
"unicode": "1F459",
- "digest": "7612fcb72c005ae7172260825f588d6995f2bc919cb3d283dd4591f6872a1855"
+ "digest": "07fe156f64673818d69ce3bf03950ca59e3b5d346e45ca541da4078ab791f5ae"
},
{
"name": "biohazard",
"unicode": "2623",
- "digest": "81f8309318051255ed4dc18855a3cd3f8657a6f3b2d368caa531a57ce0e34235"
+ "digest": "96163e31f0b8dc5a59772133ede9cc2f40f94330d0b15e3d044b28747e2be788"
},
{
"name": "biohazard_sign",
"unicode": "2623",
- "digest": "81f8309318051255ed4dc18855a3cd3f8657a6f3b2d368caa531a57ce0e34235"
+ "digest": "96163e31f0b8dc5a59772133ede9cc2f40f94330d0b15e3d044b28747e2be788"
},
{
"name": "bird",
"unicode": "1F426",
- "digest": "3f219e5aa18e2f1febfd368ec133786cd2eab357db79984cb8ba07fed0eec7cd"
+ "digest": "f916eaf8f271b3767ade9eabb69594c0479f45472d471cabaf59f6e965c161e0"
},
{
"name": "birthday",
"unicode": "1F382",
- "digest": "9eb1adb0170ab851042cb3da8b64f02f4e4b63e7a07db405b55b50f5bbd3cacf"
+ "digest": "89e7c4c598ebee8ec8ab11ebe4ccc6defb7c4d2987ee2379a19b3b59827dd98a"
},
{
"name": "black_circle",
@@ -762,82 +762,82 @@
{
"name": "black_joker",
"unicode": "1F0CF",
- "digest": "1eb85b8e2b93dec221a97a1c309dee3683408f6166e1a1a1bd83cf2f64f007dd"
+ "digest": "d004b25f186494d5b2c65204caa9daecd749c840a0bea5718735e18109e5394d"
},
{
"name": "black_large_square",
"unicode": "2B1B",
- "digest": "0ff2112227c38ed8c30b0bddf2300e87d2a244cd7fe81886a1cb1a287a7e8bb6"
+ "digest": "cbd90dcbc2f674eafa53820548b5263c18c9845ab39937f085e85aca0aebb479"
},
{
"name": "black_medium_small_square",
"unicode": "25FE",
- "digest": "f1010aa694084ad4655a9d4ce5a1711eaab21029e31bf8798253f0ad644e8abb"
+ "digest": "ab38363c2e862b8f67c719397a09a18e1ef996eec190691fdf769f5cfb209660"
},
{
"name": "black_medium_square",
"unicode": "25FC",
- "digest": "06bf48ffbc84e71bbb90aa0f6c3f9f53533c6fd063ff168cefdb0a050dcf8302"
+ "digest": "c9ffa87c37e8ee65fadcf755176949901aec7367e02abb85e63cad60cd922116"
},
{
"name": "black_nib",
"unicode": "2712",
- "digest": "c1361df4a5ae9f2ed121d26928021e96c6865331861e1960700d39cb1bd49355"
+ "digest": "58fb23b1155102970eaa23765e7d529a21e8e545e076ec1158bf11b4de5f51a8"
},
{
"name": "black_small_square",
"unicode": "25AA",
- "digest": "d430ec419869fa1b5ba980ddeecb4c5ad5050a2b3421e45048cc184a6fc46899"
+ "digest": "f69be6de578fffce5a3e60eda690104b2ef6a855c630040104fb760a02ff1aef"
},
{
"name": "black_square_button",
"unicode": "1F532",
- "digest": "85b6587b6b2c3544ddb7bc07207b0740e437744ba134835836153899ae396135"
+ "digest": "9d818fcd08ed38cd0bbbcfd83e665aa29b3761c0d8b9806d8954d36785e267a8"
},
{
"name": "blossom",
"unicode": "1F33C",
- "digest": "029bbe385e07e2017dd918d685e107678c9c0e919a3bd1521b7a0d7c9172da05"
+ "digest": "e8cf369d4e4cdb4eccc2ebcbb35439b0344221115701daae642e58dff8544922"
},
{
"name": "blowfish",
"unicode": "1F421",
- "digest": "b5ee9f6ffabb74e3024067f016d17a631ee98536cb9c7269d55fa867f95a54fb"
+ "digest": "e706849ed00f08a82312381c76f6f9ba6cc261fbf87a839c85e7dd54138f9dc3"
},
{
"name": "blue_book",
"unicode": "1F4D8",
- "digest": "6fbf227fb9facc1957bb9dfb31749cbfe66c3afe8081347f2471fd64ef2e6b3a"
+ "digest": "4c845748fe890516b32981b0b62bf3e8e9d906840c2060179f4f844100780615"
},
{
"name": "blue_car",
"unicode": "1F699",
- "digest": "e61ef2299d11fc01e9d6c496d188a7211633946706f6e771c412368346ca16f4"
+ "digest": "eca91934eb5481726cfd897b1ed5eac306e14d02499fbe49316aaec6c72b6707"
},
{
"name": "blue_heart",
"unicode": "1F499",
- "digest": "1af8d04173e0a984360786f6031220000dd548b8c912a68fd51f2ba490a9e16a"
+ "digest": "2caa0c8d18538cc871c6fe328a52f71e1df8aabf4d1cc2f5324b261d1b8cb99a"
},
{
"name": "blush",
"unicode": "1F60A",
- "digest": "d615cda0f7c185ed8a92008204043ef769f3b7fb5424d595aeaaf3827bcdbd73"
+ "digest": "3bfe8d603cfa39999c164779f666d39bbc507f124ba80233ee72da7b3b0c0457"
},
{
"name": "boar",
"unicode": "1F417",
- "digest": "c23a06db0337597e361ae581eacd4faf9926c6b7db0510d3599eb2e2a73315cb"
+ "digest": "c9d67479cace427ac3c30460fcffa1bf9a8e5262c0390962405dbbe6bf830fa6"
},
{
"name": "bomb",
"unicode": "1F4A3",
- "digest": "0099e7435eba35f4f3ad273993293693a8b5cd110567c95ed83e5b4e2d0978ff"
+ "digest": "0155559abc4084f80e9b0b2a2091b8710ddd6369993b7fdd0685f4f8c2fd7e6c"
},
{
"name": "book",
"unicode": "1F4D6",
- "digest": "152408f2ff9949b7cbe57f623e4f875aa8dd0b02317e03cc914e1ea3712b3fc7"
+ "digest": "9d912a9d1bb10dc7f2645b345ed09e90461e83df0de275acb806f1f75cef1fcf"
},
{
"name": "book2",
@@ -847,32 +847,32 @@
{
"name": "bookmark",
"unicode": "1F516",
- "digest": "a2e0c6f5466c1b2fc148b20f6afcf4a878f4df55b0181f61fffa3ff727dcb251"
+ "digest": "5705e3108259d6900649157843c50e22d0086c3630b291d3f942da1a736e3e3d"
},
{
"name": "bookmark_tabs",
"unicode": "1F4D1",
- "digest": "16135d62ff440722bd1ce8f84219be6a5eb3120a1597bfda4aeed4a2d9e7d7b2"
+ "digest": "c8fc7c9f3f82e1ccc97fc591345fdd88b09eec0fca428d8d4632a121cf1bc39a"
},
{
"name": "books",
"unicode": "1F4DA",
- "digest": "ba019e4174639440caec424b30dfa016fe71a6f7436fe63025a2e3609ebfc012"
+ "digest": "cbcf55d39dd05d26ef7350bc51e0e2f064f78bb8f59d407b516d63f68558f8e4"
},
{
"name": "boom",
"unicode": "1F4A5",
- "digest": "ec26246935c99749950612d69c06435ccdc126f14426a48a7599c5b6b91d9d58"
+ "digest": "f5400e9583f7f997cd2385f21379f6229424a9b221445bc8f36c0bb64bdb3168"
},
{
"name": "boot",
"unicode": "1F462",
- "digest": "7ed639d52e285b0f46064dd4e1f4a8fb5814e1b2dc47c6f93cb349a6ac7ea97a"
+ "digest": "b4706ff35909a6fb759a3b8a797e90cb67ffc60e4853386a7d89ace9693a9364"
},
{
"name": "bouquet",
"unicode": "1F490",
- "digest": "b699f13af218560344f3571436f87b6f8c5c9f0fa0308836937667241b3fc7aa"
+ "digest": "b93751a27b40f6185a22b3e8b413f0fe09b6010d1057c672e1a23088e0b8286f"
},
{
"name": "bouquet2",
@@ -887,77 +887,77 @@
{
"name": "bow",
"unicode": "1F647",
- "digest": "5e260c38cfc80cd2f20ef78d982126dbf90934f7afa12c96d0b7b413beb6d4e0"
+ "digest": "33cd6da4d408f18d98bebc6a277dea8b914150e32ee472586ce3f1eb814462bd"
},
{
"name": "bow_and_arrow",
"unicode": "1F3F9",
- "digest": "1c23469256331ea4ff03c036f89f0e63ad3228c51faecba50129da99b7eaddf3"
+ "digest": "051b4d50ab21a68b8583a6313ec183e3e1e96f493b0f4541fbb888f0b95fdd4d"
},
{
"name": "archery",
"unicode": "1F3F9",
- "digest": "1c23469256331ea4ff03c036f89f0e63ad3228c51faecba50129da99b7eaddf3"
+ "digest": "051b4d50ab21a68b8583a6313ec183e3e1e96f493b0f4541fbb888f0b95fdd4d"
},
{
"name": "bow_tone1",
"unicode": "1F647-1F3FB",
- "digest": "d3ec7ef70b355ba310d6fae7130a4e4cd11526b6e219474b5678a2b3ba1077f0"
+ "digest": "995c8400ad60d5adc66c9ae5e3c0ecf56c48b478ad79418d45b6289933d25bdd"
},
{
"name": "bow_tone2",
"unicode": "1F647-1F3FC",
- "digest": "c2905c0feba15fbc533cc6b36038eeda30f729182aa544f1d9164f5ccfed64d5"
+ "digest": "af89eec2fccda99d9bdd373b2345595882fee1c0a15d29af9028089e20255325"
},
{
"name": "bow_tone3",
"unicode": "1F647-1F3FD",
- "digest": "298fc646d96c307eaa137c80b403d8355539ed8af13d3954a4ccacef67d341fa"
+ "digest": "015d8122abdf2d0caa03815545f50fb7a71e05dacd46aaa133cc9ace5192f266"
},
{
"name": "bow_tone4",
"unicode": "1F647-1F3FE",
- "digest": "27db8401aa62a2544b24ff839b332958b5e8c3ab3fd7a289d3c62c654705da60"
+ "digest": "e8409096a795b775def654d36aeccb8eb91e83d7d1b32145cd73fd0b7b9e885c"
},
{
"name": "bow_tone5",
"unicode": "1F647-1F3FF",
- "digest": "168cdf834edb54723cf1c32311d4117c288132c5f76d6c415726c7484158c52a"
+ "digest": "d87042cde8dbad9fb1a91a2ec60116e27b4a76388b5779d771a0bbae12a2814d"
},
{
"name": "bowling",
"unicode": "1F3B3",
- "digest": "0e888bcd1a5cc1ea7b07cea255ccb04dcdc87b0337b74cdc96a708aad7975768"
+ "digest": "737f2cdfa4ac964baade585a39771b18080bd5e9b55c8661d3518f468f344662"
},
{
"name": "boy",
"unicode": "1F466",
- "digest": "f349ab3e1015b4ccda5faab6a355f9c38e36e7c1cd667084563a14a2b11036ea"
+ "digest": "7bc0173d8c88f3f12d41f213f7a3a9f5ebf65efad610fd5a2a31935128a6a6c1"
},
{
"name": "boy_tone1",
"unicode": "1F466-1F3FB",
- "digest": "4d04a5e45c9f9749de580321a212e14304b4ffcd229fa971fb59d97e6124262f"
+ "digest": "c0e2f0483715b239fe145b0056566f7a3a722319d9a87c1e66733dff1916a19f"
},
{
"name": "boy_tone2",
"unicode": "1F466-1F3FC",
- "digest": "0c9d6b6b1b3da68b9ef1f0f01efa4d170a48cfc66de4f577f8669c160b81cc97"
+ "digest": "0001d0bd1ff4dbd898604ba965b4039d09667d955bc0349301b992f9ab6dd7fd"
},
{
"name": "boy_tone3",
"unicode": "1F466-1F3FD",
- "digest": "7dbecace78edb2aceffce6cb4d49ca132b93d80c26a8f1526a18832a2f23454a"
+ "digest": "e0f08755955fd2e0bd1c5d5e84429b2a234b24a744bb50bb9f1148495b2b29f9"
},
{
"name": "boy_tone4",
"unicode": "1F466-1F3FE",
- "digest": "49f9c633afa8ff81068c78717e0012f8936fb3dcdb8b57342410f57f0635ae7c"
+ "digest": "04b6bfee58a26b1ce2e5b403504a7033aaf395f03f5cd23e824f32c90c395fe6"
},
{
"name": "boy_tone5",
"unicode": "1F466-1F3FF",
- "digest": "17e2ec379c7b542e6c2c5deef992af5f1fbaa3e288d1f71c8c984fb91a698cd4"
+ "digest": "0f76e97237203950da36c737dcc6f56dcd6c123401a8c817a0636376c7f38ef5"
},
{
"name": "boys_symbol",
@@ -967,72 +967,72 @@
{
"name": "bread",
"unicode": "1F35E",
- "digest": "43697495538bfed11ed75213af8b1bdc14ef359d9b472cd7f9130fcb0a198680"
+ "digest": "81739830f16f33e6a1dd7cc17c25df207846062bb5167bb8abed7fdd49268b86"
},
{
"name": "bride_with_veil",
"unicode": "1F470",
- "digest": "37e75fbb2b0d06c900d51269b99107c60b61453dbf218b54df3011a455cd6dc3"
+ "digest": "8e24bd91c3f564cf6148f2b3b4a7d692c11dd059e76a13331fdfb04ae060ea70"
},
{
"name": "bride_with_veil_tone1",
"unicode": "1F470-1F3FB",
- "digest": "44072e54e0618d2675a5bfd6572108590e51e8e733381e091e8754ee96c2cf20"
+ "digest": "0bd2f16f72586f50e768b14b9b353f2e98ccbb2581a568c33b06be56e70ca063"
},
{
"name": "bride_with_veil_tone2",
"unicode": "1F470-1F3FC",
- "digest": "f0acd961e108db9d9dd5d1b06e708b2eb6a7ef7235d6c8678b9319077faf4fa8"
+ "digest": "e5463f811b2075754f0718b891757cd2e81071edf7af2215581227e1aad1d068"
},
{
"name": "bride_with_veil_tone3",
"unicode": "1F470-1F3FD",
- "digest": "3f7adddb41ead3cd07098799ab2a5b8e8842344307d9045264403fb685f20555"
+ "digest": "e5a053a26f7ccebae7eb12f638be5ed80f77b744708d783eab2eb8aa091cf516"
},
{
"name": "bride_with_veil_tone4",
"unicode": "1F470-1F3FE",
- "digest": "5f7199fd99319651f3a7b3553cc5387c59b65cac1eb020441e19b5c12c807dc7"
+ "digest": "410e23825e4401460946dc67a618bd3ace6e1a7c07dd88580a2349423685261f"
},
{
"name": "bride_with_veil_tone5",
"unicode": "1F470-1F3FF",
- "digest": "4b1f6c33dd72a3a11c764bb00e7be7441b39c7af78aae52141276a279d63ab78"
+ "digest": "454e87e5a74e13e5b4993541231516fbbe6dbe9f990e1a6f3f4a744d7d4c1615"
},
{
"name": "bridge_at_night",
"unicode": "1F309",
- "digest": "f81cc36de8edbdf3fe4d55932d5c6c8ad429487ec1f7af044611b6dc950ee09c"
+ "digest": "9d3cda5a59e27e3c90939f1ddbe7e998b3ea4fcacfa1467dea0edf39613c2d7f"
},
{
"name": "briefcase",
"unicode": "1F4BC",
- "digest": "a3c3e802191f3e131683dac1fcd81e294dea72af8e65c94972990924c79c5619"
+ "digest": "9d00d6a92632aaadc71b017f448c883b27eb31a7554ebb51f7e3a9841f0f7f2b"
},
{
"name": "broken_heart",
"unicode": "1F494",
- "digest": "4dee349274c2ea44d1c0395cbd39356b88897b0c45040aa40d8cb2607ee67420"
+ "digest": "c7ca53f444d72e596af46b61ffbc9e7c18a645020c22691e44f967db98dbf853"
},
{
"name": "bug",
"unicode": "1F41B",
- "digest": "bac4660ee8dcbef0023691804ee3fad3ea3d4bac20d847a5913cee6e7dca826c"
+ "digest": "0dccb1d5eb91769377b4c5b310f007b60f54a5c48ba9e467b3a06898a4831b90"
},
{
"name": "bulb",
"unicode": "1F4A1",
- "digest": "af5394230f95781c7eb8054b1a13732a6e6170318599c79e9ca2a816a5b821a2"
+ "digest": "ccdaa2dfde5a88a347035a94b9d4d86cfc335ce0a73292423f5788a4bd21a5a8"
},
{
"name": "bullettrain_front",
"unicode": "1F685",
- "digest": "59afcd289500bd4148b1b91f560a5ce8ac9e1b52eddb8fec857ff5d171f017fb"
+ "digest": "5195a6a6d23f28e1aa5ebac6ede0f6c6a8b7ff33a9edf034814f227fe976177a"
},
{
"name": "bullettrain_side",
"unicode": "1F684",
- "digest": "79ff8f579081a2f1c3b05311a18ca432adb026a7860875cea4a5460e49b2a474"
+ "digest": "96e74842e919716b7bbbab57339bfd70f099a9bcb4710dffd7c80cf38a7bbff7"
},
{
"name": "bullhorn",
@@ -1052,37 +1052,37 @@
{
"name": "burrito",
"unicode": "1F32F",
- "digest": "4babb1af1136ab2334d26495b0be779d0bcc9516fd956fc07ffde427d11122f0"
+ "digest": "b2cf81f1efdf87e674461f73f67cd4b58a5f695e65598d0dd3899f2597da43cf"
},
{
"name": "bus",
"unicode": "1F68C",
- "digest": "476e7a5e92f64038e5012205395efead51f1c10b3edb25380f38da97e2412edd"
+ "digest": "192850b762edad21ac8770df38b9cae6d2bc1697a838462f3e36066bfb4eee50"
},
{
"name": "busstop",
"unicode": "1F68F",
- "digest": "3bcf82872ab6abb0278238c71bd004a40c46696bdda05f54c153d45d6fe88f15"
+ "digest": "adabb1ec36402b33feb636eae3656e5a8b51ff1071bcb14125d8ab80d6d12d2a"
},
{
"name": "bust_in_silhouette",
"unicode": "1F464",
- "digest": "2230844993ab011fe2756a1aa3873ff7d5f7d888bddec408ba0b32e4f6003570"
+ "digest": "277ae43301f1e49e0be03c8e52f0dc7b70c67f9d146bca0a14172e0098f115e6"
},
{
"name": "busts_in_silhouette",
"unicode": "1F465",
- "digest": "d1c3cb6d437616834425a53621c0bc0a6b368d745dd9da2300a3db4543d57660"
+ "digest": "7fee96f1b68bb2c6002e47f2ed13c06baa6a3168441b9aca572db7ec45612f7b"
},
{
"name": "cactus",
"unicode": "1F335",
- "digest": "e87588e6548d201db903dc0523b3ccc83c6b559981d743eae1504ce668cd8be4"
+ "digest": "2c5c4c35f26c7046fdc002b337e0d939729b33a26980e675950f9934c91e40fd"
},
{
"name": "cake",
"unicode": "1F370",
- "digest": "3947783d128018f5e396602d0492cb5c31e8e8df98af01eda7cade71aea8d989"
+ "digest": "b928902df8084210d51c1da36f9119164a325393c391b28cd8ea914e0b95c17b"
},
{
"name": "calculator",
@@ -1097,42 +1097,42 @@
{
"name": "calendar",
"unicode": "1F4C6",
- "digest": "00bb700dd88efbc43bc64263491cdf77965130b1dc23f31e682905c3dfe4040c"
+ "digest": "9d990be27778daab041a3583edbd8f83fc8957e42a3aec729c0e2e224a8d05e3"
},
{
"name": "calendar_spiral",
"unicode": "1F5D3",
- "digest": "1dd5da98bb435c0c3f632bc0a5c9fdde694de7aee752bf4bb85def086e788a2a"
+ "digest": "441a0750eade7ce33e28e58bec76958990c412b68409fcdde59ebad1f25361bb"
},
{
"name": "spiral_calendar_pad",
"unicode": "1F5D3",
- "digest": "1dd5da98bb435c0c3f632bc0a5c9fdde694de7aee752bf4bb85def086e788a2a"
+ "digest": "441a0750eade7ce33e28e58bec76958990c412b68409fcdde59ebad1f25361bb"
},
{
"name": "calling",
"unicode": "1F4F2",
- "digest": "2375828085f2efd17b8a5ebb3cfec1e420190913328a7a0dd9ff0f67c7249ffb"
+ "digest": "acf668c75c11c36686005788266524a972fa1c5bcf666ff3403d909edc5cee91"
},
{
"name": "camel",
"unicode": "1F42B",
- "digest": "9ff789ab50b51cd9e7fdc7fbe8d6f913fda95dfd425949f97974548652a53ce1"
+ "digest": "5f927927a7ab1277d0dc8b8211436957968b1e11365a8bf535e9bb94f92c5631"
},
{
"name": "camera",
"unicode": "1F4F7",
- "digest": "d95192b9ba0f566d8874099125def031e15297d1306989ea9b6a49f7b9b56661"
+ "digest": "fde03e396822a36cd6ae756ede885b945a074395264162731ca5db47a3b39d80"
},
{
"name": "camera_with_flash",
"unicode": "1F4F8",
- "digest": "4db6fb3fdb9a004537dff97f4197c7ed87c9c978ba9ac562ed8bb7c1fa260d38"
+ "digest": "9afd380208187780f00244c45d4db6c5ea1ea088d4a1bd8fc92a8f3877149750"
},
{
"name": "camping",
"unicode": "1F3D5",
- "digest": "f0855dc78bf6f3d06b3c2fc19180c8ff23d9e22871658fcc26a8fde08d328a0a"
+ "digest": "a42a4ff9521affa72db7b0f01da169b4cb6afb9db1c5dfad47dd4c507bfc30d9"
},
{
"name": "cancellation_x",
@@ -1142,47 +1142,47 @@
{
"name": "cancer",
"unicode": "264B",
- "digest": "b990f85e9f62017d99526244eaef5c5e56f8808698011e85d44de1d2ed87f1a2"
+ "digest": "528c6f21df99a756b553d93a7f395b0f662b30a323affd05f0cedee8ff7b41d6"
},
{
"name": "candle",
"unicode": "1F56F",
- "digest": "5eefd555951e65298583009a307acc6fb6d02c88325ef3adf231717e75e5a333"
+ "digest": "211c04dc3a91b071c284d4180ed09f9d3320e3fd6ba8a9fddd0677bc97fd12cb"
},
{
"name": "candy",
"unicode": "1F36C",
- "digest": "f14203c408173fbb94b4ee69d6de67226a17dc51b0cbd776f62623ee03fd2eb3"
+ "digest": "9cff4538918f60f770fceb96e964f5dc3ce31fd08ddd2ab3bfdf2981bfa74100"
},
{
"name": "capital_abcd",
"unicode": "1F520",
- "digest": "2a7cc876218b8c244b9802448ee25ce5004671a4f00ea950a636d8c3b766dbef"
+ "digest": "a416d0b3f564037b680f801fb773b6eaf67225e2cbbfd2cb8a5db0de044321fa"
},
{
"name": "capricorn",
"unicode": "2651",
- "digest": "03a5fd064c10f47c7fd0ae318c573bb559c269b1b2d61b45aa5b8ce9b5fbd9df"
+ "digest": "f11abad102603737b55486fe2ea4d01f28b203394bcd84f19a7948156e6c4b96"
},
{
"name": "card_box",
"unicode": "1F5C3",
- "digest": "7d760ae1d44e6f4b2aac00895ca86b5743f8b5ca157ec2bd21ce2665e50ad23a"
+ "digest": "7a6199d562f30e02ed31094de6aebeb99eae8ac156f6910463dfed73256f4c9a"
},
{
"name": "card_file_box",
"unicode": "1F5C3",
- "digest": "7d760ae1d44e6f4b2aac00895ca86b5743f8b5ca157ec2bd21ce2665e50ad23a"
+ "digest": "7a6199d562f30e02ed31094de6aebeb99eae8ac156f6910463dfed73256f4c9a"
},
{
"name": "card_index",
"unicode": "1F4C7",
- "digest": "150950903eccb468981c58b87ed7c1ba44e17f52627d695f660ce96b3d9d6e8e"
+ "digest": "86e187e0a72ca5d00207d6ef34d66ce15046848a831c2b5184fb840c5332a2a8"
},
{
"name": "carousel_horse",
"unicode": "1F3A0",
- "digest": "d6862085550fa139a147dceb1b2b9f950a08dcd01cecd8b8697f9c7992ca054e"
+ "digest": "c0e7059efc39a64233f774c02ddb1ab51888fff180f906ce13a6e4f9509672fe"
},
{
"name": "cartridge",
@@ -1197,17 +1197,17 @@
{
"name": "cat",
"unicode": "1F431",
- "digest": "002208c0c9165971853ee05cd05513175a913376a462a345a939d73401c6acb7"
+ "digest": "e52d0d3a205a0ba99094717e171a7f572b713a0e21b276ffa4a826596fe5cafc"
},
{
"name": "cat2",
"unicode": "1F408",
- "digest": "fbdb726cc035f83784dcfe2d9adb85f8aeec429064aed5c5ca0b8be406068aa5"
+ "digest": "46aa67a99f782935932c77b8de93287142297abe52928c173191cf55bb8f4339"
},
{
"name": "cd",
"unicode": "1F4BF",
- "digest": "bd4d4eef2cc0b1e4ee1f5280f922743e76f27d35836987801b2b48969eac17d8"
+ "digest": "16363d8a34b873c12df6354b99f575cae3d80e0d27100ed7eea70f0310953c7b"
},
{
"name": "celtic_cross",
@@ -1217,302 +1217,302 @@
{
"name": "chains",
"unicode": "26D3",
- "digest": "a6a915d9c361e1564e13cf2d33ad5df3d684aa349b8dc5909e6343d67401beb9"
+ "digest": "3884cdbc6f2b433062af06f942552e563231c24727a2f10fa280b3bb7aa614e2"
},
{
"name": "champagne",
"unicode": "1F37E",
- "digest": "77395d3afe5cc10bfdc381120bae2ae4aefdaa96c529536413873a696c5fa713"
+ "digest": "9e6e8987f30a37ae0f3d7dab2f5eeb50aa32b4f31402b29315eb2994afc72457"
},
{
"name": "bottle_with_popping_cork",
"unicode": "1F37E",
- "digest": "77395d3afe5cc10bfdc381120bae2ae4aefdaa96c529536413873a696c5fa713"
+ "digest": "9e6e8987f30a37ae0f3d7dab2f5eeb50aa32b4f31402b29315eb2994afc72457"
},
{
"name": "chart",
"unicode": "1F4B9",
- "digest": "9fd5f8cd99988bbe0fabc89a0b23e28d1468641d2f9468e82b7148a1948d8236"
+ "digest": "a092dbc08f925b028286b2b495a5f59033b8537a586a694f46f4c1e7c3a1e27f"
},
{
"name": "chart_with_downwards_trend",
"unicode": "1F4C9",
- "digest": "6fe456d76c0a996c12049057b5d60129098a9deddfa2d133cff5c4400e4595a0"
+ "digest": "5db7ccbc37665736a9c0b2f50247dcc09e404ec37f39db45b7b8b9464172a18c"
},
{
"name": "chart_with_upwards_trend",
"unicode": "1F4C8",
- "digest": "e83cc4cf4228bd77e030a19755b11cf75cf671f40973c23e240afa54d9de478e"
+ "digest": "bc4ea250b102fe5c09847e471478aff065ad3df755d9717896d38d887d9c6733"
},
{
"name": "checkered_flag",
"unicode": "1F3C1",
- "digest": "77501c2c66af31f72f5c05f21e87598cd59740b5cfc02926c66dc755bab3c3cf"
+ "digest": "0e77180e0cf9fc87e755a5a42cf23aec6bf30931db41331311e97ba0be178b78"
},
{
"name": "cheese",
"unicode": "1F9C0",
- "digest": "5897036ba97b557868bb314fcee83b9d8a609c8447b270a0b3d34a29ce7496d1"
+ "digest": "50a6cb906c2120e2bbc0e22105924262007cfe1554d7b02b8cc84b6adedc6a0b"
},
{
"name": "cheese_wedge",
"unicode": "1F9C0",
- "digest": "5897036ba97b557868bb314fcee83b9d8a609c8447b270a0b3d34a29ce7496d1"
+ "digest": "50a6cb906c2120e2bbc0e22105924262007cfe1554d7b02b8cc84b6adedc6a0b"
},
{
"name": "cherries",
"unicode": "1F352",
- "digest": "5a0ba73039e4b56e3d16a1c70ad992f41af7a16f6d5ba4b5337bdf338276f0ff"
+ "digest": "13b8db9e7e6eec8509aa80c762966e1bf3538fcb1ac3d6eab18ee4da1528cf84"
},
{
"name": "cherry_blossom",
"unicode": "1F338",
- "digest": "b40533225291f539ffe97e4ab1d70d07e179b2f9345b2814355164d0407cf3bf"
+ "digest": "af3083f5f8dd94936113f2e16caba5aec7a774d5589aa08bf5de82a2d278cc66"
},
{
"name": "chestnut",
"unicode": "1F330",
- "digest": "6a2a37899d28326daf36965b343b2646492c2c0cee8871321cc17315d6252a9a"
+ "digest": "9f85b79b207a69ab81ab88dcef04954000965b039b4cf57de5f1b381745ab98b"
},
{
"name": "chicken",
"unicode": "1F414",
- "digest": "13d770684a11ea10c0ae7570a98c5dfafd4bfb78ac3f72f46729aef9060b85c0"
+ "digest": "57ceb4459d183740009caac6ebed089d2f1e12f67c138e1be1d0f992313c0ac4"
},
{
"name": "children_crossing",
"unicode": "1F6B8",
- "digest": "654d2502c1edc57c5ab4237df76db3121f6b8735eb13d30bffd305605a083445"
+ "digest": "0ded7d9aca0161e8ef8e2858c3c198e70e4badc7105ac3a6886e06975de19106"
},
{
"name": "chipmunk",
"unicode": "1F43F",
- "digest": "1ae3c838450afcbbe8a96992481dde252e343ab83546d0789ebed81a78ca9188"
+ "digest": "5b0dc1a859163097727ba2ba5ffca38b0a54d925eebb089977d28d0b4d917a3f"
},
{
"name": "chocolate_bar",
"unicode": "1F36B",
- "digest": "2486b7265048eb2294d6be0a0a8a4d6067df95721ace9d131d8f715a27ba8cf0"
+ "digest": "dd273e5050488acaf885f8a18b6e2b3901f69c5b39fa6465fb60621783d4109a"
},
{
"name": "christmas_tree",
"unicode": "1F384",
- "digest": "454c08870eaa84283c19731ed3b10c4868d2e2f0cc44f2feba0de9ba4cc9c4e1"
+ "digest": "ce60cbe2ebbe8057be8edea2392455fedd2bcda64a0a831f6a1942028af7e747"
},
{
"name": "church",
"unicode": "26EA",
- "digest": "b62e838ffb0dfefeced1707359437b6815e0721783b549212282e08617402f6f"
+ "digest": "2c328456528f7336e59443e20ec3ab22fe71f1fccb1dd50d0ad68eb206937557"
},
{
"name": "cinema",
"unicode": "1F3A6",
- "digest": "6df56f6a0008d0352740d1e045ffdb702e80c2a6d88b6db1a8bcd27eb3c12dcc"
+ "digest": "4c26dcdc76f93dbc2a1dc49ed4e132b8e8f2b7cdc1acf5e09b3dfd99430d97cd"
},
{
"name": "circus_tent",
"unicode": "1F3AA",
- "digest": "f8b7a7f4cf4f9efd20423acc30abb3a28e2a5183b3e39f5cc88e7e0ed7757d64"
+ "digest": "fec5f2a06222be8be549178b29720343cc00145177ec387ca4e6f3432481fe77"
},
{
"name": "city_dusk",
"unicode": "1F306",
- "digest": "8779066dc9386d05c951b1df1753983c2937a5f3b84d5fc09ed0b172d4ef914e"
+ "digest": "bba345e949dcc51f5f018220f000223797970c82ead2ab9c822f9dc0847aa155"
},
{
"name": "city_sunset",
"unicode": "1F307",
- "digest": "c2530d12204eb518c5a3c8d7deba11170b1412fdf406aea05a69d4c026210d1b"
+ "digest": "a846df1a4c7c778f8e1729804aece86eb29d2fcb95dc39eaaf2aae1897f3dcc7"
},
{
"name": "city_sunrise",
"unicode": "1F307",
- "digest": "c2530d12204eb518c5a3c8d7deba11170b1412fdf406aea05a69d4c026210d1b"
+ "digest": "a846df1a4c7c778f8e1729804aece86eb29d2fcb95dc39eaaf2aae1897f3dcc7"
},
{
"name": "cityscape",
"unicode": "1F3D9",
- "digest": "15251a708d50fc721bd67d8abb2a517c0bade196df3b736e21d79191d749241f"
+ "digest": "ee360be7514c4bfb0d539dd28f3b2031ebcef04e850723ec0685fb54bd8e6d5f"
},
{
"name": "cl",
"unicode": "1F191",
- "digest": "104591d8e7b980cf38dcf8326d36c845384b7a4e6d94c49f36e9946484712a95"
+ "digest": "fcec2855dbad9fda11d6e2802bc0dcaabab0b5be233508f5e439f156f07602c1"
},
{
"name": "clap",
"unicode": "1F44F",
- "digest": "ed6ef8bb78ca1fa295b87222c440c6d5ba4f154f2752bf0d428941260d66aaac"
+ "digest": "a1860ce7812a9f6fb55e45761e1b79a2f8f0620eb04f80748a38420889d58a2a"
},
{
"name": "clap_tone1",
"unicode": "1F44F-1F3FB",
- "digest": "57a1fd1fa2578c30b8a47abb84e81af5f5bbc6c301a5daf0c53d4d07b017e777"
+ "digest": "18a7022e08223fb2109af5a9b9a5b4f47dc870ce4453f4987d2d0b729ef54586"
},
{
"name": "clap_tone2",
"unicode": "1F44F-1F3FC",
- "digest": "2ad4dcd513e55486f21151bf3792e1febf116574d238545b07b4290901430fdd"
+ "digest": "5954c8658b15e755d2018d8674df84d38e22ffededc4d726c6a33b709f71426a"
},
{
"name": "clap_tone3",
"unicode": "1F44F-1F3FD",
- "digest": "2d8c705d4fcc162fb65cd51e2c6683f1129ebc72fba13343533f64ede1c62687"
+ "digest": "22639b6bd3c53784a2f855d6db7bdf31621519f19dfc29a6bc310eee6421f742"
},
{
"name": "clap_tone4",
"unicode": "1F44F-1F3FE",
- "digest": "40ffd41b2b4f59d0040e9d20497e57c4e47f18aeae43fcae02be5c2f50069102"
+ "digest": "e55248dc163d1bbd118b50cd8767750ead86d082151febbc0a75b32d63abceec"
},
{
"name": "clap_tone5",
"unicode": "1F44F-1F3FF",
- "digest": "be55df1ac7600ba086c2ef6ea223ebc62271fa47876c53ade1a1c0151fdc994c"
+ "digest": "76046b8157dabbe048a07fc318122456020c9c980fc1b8ab76802330e07b3b53"
},
{
"name": "clapper",
"unicode": "1F3AC",
- "digest": "a8748398f56fd2c1e6e87fe0c77edec444df7c7dd462d43dbcea6d8de97c81c5"
+ "digest": "8149752a0e3e8abede2d433d1afab6d217877d0c76adb1e2845a0142c0cdcbaa"
},
{
"name": "classical_building",
"unicode": "1F3DB",
- "digest": "6a607b0666141b51d6e944b04f3f6188a5c026396e6105f1d2a5e6b6350cd66b"
+ "digest": "9ee0d00c43d6e22b6a3ddea67619737270cc7e9294797a19c7c60d5f92aa44fa"
},
{
"name": "clipboard",
"unicode": "1F4CB",
- "digest": "4ca1a0b864a962b111d6bdb65373b779f3fff571ffd32d029666f9b708e1ab73"
+ "digest": "bdd7f7d973c714e59d2903d401a876e6018794c7987c9ca57108c137c5edc25f"
},
{
"name": "clock",
"unicode": "1F570",
- "digest": "c48314ccde8bf01acc2b1bc9a6b5aa7d796fc0c8769f80398bc74545fcef31ed"
+ "digest": "302835eab2637db799acf69b3d795571ef3432251267050db0704f2954e8b190"
},
{
"name": "mantlepiece_clock",
"unicode": "1F570",
- "digest": "c48314ccde8bf01acc2b1bc9a6b5aa7d796fc0c8769f80398bc74545fcef31ed"
+ "digest": "302835eab2637db799acf69b3d795571ef3432251267050db0704f2954e8b190"
},
{
"name": "clock1",
"unicode": "1F550",
- "digest": "c0550fa0c385920cbdb775bdaaa5e812097a484c4a32e35ebbafe3a364a4a438"
+ "digest": "1778eec07ce061c9393e5abee5ca83b24e1ce61d8a75fa2e39efcb31aa160395"
},
{
"name": "clock10",
"unicode": "1F559",
- "digest": "25651ac5520505f326457364428de3679cc22ca57278d4c54cc4b60420fa7b74"
+ "digest": "601fc12ea5280a54c2e69dbb685f454e4165fe771756ed6f89016e29e683a24f"
},
{
"name": "clock1030",
"unicode": "1F565",
- "digest": "dbf682bac968fc5a3959af2b96eaaa5ee78306f6341c43c1345b94bc561a3d04"
+ "digest": "4fd155f08f797542d52cff4b0aa3ca9f080f37a41c301b82f90ff6d4693c890e"
},
{
"name": "clock11",
"unicode": "1F55A",
- "digest": "333732dd6c3184f257964bcf5a20a6111f9adb04560b5d12dc613636e846df5b"
+ "digest": "5c79dc812e812e8a01993ea633b323d654ce3a7ea258692781a4896e4ad2017e"
},
{
"name": "clock1130",
"unicode": "1F566",
- "digest": "005999cb37998adea1645d7df63b2705a42db3b4f1a734891d79af3e833764ff"
+ "digest": "41497ee2020ee5ac9aa5f9b07560f7afca7c422b04214449cfc5cea9f020f52e"
},
{
"name": "clock12",
"unicode": "1F55B",
- "digest": "6690e591bec1751e1c5472e0bf52f66779b2113e5b8c6c578e65dbb83d091b16"
+ "digest": "046bb7ffa5f5d27c2e3411ba543484d9dabb8ebf6d6e7a7e9bfb088c1813500c"
},
{
"name": "clock1230",
"unicode": "1F567",
- "digest": "549f3921bcff7f330c5a41e6756d8c15601f1f8278b35b369148771c60be2a6f"
+ "digest": "bbfe9db5a2043aaba19a7a2a0185c7efcebf1e8c9263b8233f75b53c4825f0f4"
},
{
"name": "clock130",
"unicode": "1F55C",
- "digest": "9332ef07a9dde8ccaa1e58a3e97edee0601a1152fc6d351b782816c838d2a408"
+ "digest": "8662cb395ee680c2781123305c4c8ce8c0df9565c2c942668940be540cc0c094"
},
{
"name": "clock2",
"unicode": "1F551",
- "digest": "9d1ec8fbdae627880e1c067c10d6a40f1e4494a246c77224b3cd7b287554c4b4"
+ "digest": "42f7429748b612dce7de77221cbbc710655811f7bb23e2a986c36e6d662f0ec4"
},
{
"name": "clock230",
"unicode": "1F55D",
- "digest": "3578a39c28695d4e617a648a1eb44e0bb5a8a11dcbe04fa2eb2aea0a60589067"
+ "digest": "e710b6ef14227cd240ea3e2a867c8ef45b5c060adf3cb30ba9077c2351fe6677"
},
{
"name": "clock3",
"unicode": "1F552",
- "digest": "c2e2a27301b6ac27dc359be590448eb1e65fe87211f1af30a473d8bde4f3db47"
+ "digest": "7340d465b398a378211dff9ec806db579d061206fd6fc238623d070cfe0a55ce"
},
{
"name": "clock330",
"unicode": "1F55E",
- "digest": "7a77cf8cf9a98f4767a2dca1d3795be45938eee185db81120d85cedebe128899"
+ "digest": "7aa4a15cc8de04ed3bdeb0f8a54a7915065f2809a07054e002d89926c9766831"
},
{
"name": "clock4",
"unicode": "1F553",
- "digest": "0945c4199400d546350cfff25bc9e9160789d1cf9890b3318bdc462ac6cc9782"
+ "digest": "36fd88e81ad488b0ec49a911a838693281573fa14736ae4a6dd1c40a4ff69bb1"
},
{
"name": "clock430",
"unicode": "1F55F",
- "digest": "9fdb6f1fa076c4c6a395dbf6db27499ee447b3558f3aa64d913686c360e428a8"
+ "digest": "7bd5dd71e89d95dcf18b9e8c1fe2a353a7da3b69aadb8dda80ee9bafb05da58d"
},
{
"name": "clock5",
"unicode": "1F554",
- "digest": "855b3500eb6d20bb6e51d3a6c9d1a5131c06404c6c149841c7cca52201036428"
+ "digest": "aa406409e56a0bfd8c850e44efe45fd190ffd7bf7061e934ed7928dfbdfc9eba"
},
{
"name": "clock530",
"unicode": "1F560",
- "digest": "a6ebd9f884d45a1f43650351a1f1da9724bc044d7da2f6d99ffb3d1fa0c31c5d"
+ "digest": "25dd3bcc53ddd98eeea498d7dbd4c306ef39dd033f15909063388a0800febf41"
},
{
"name": "clock6",
"unicode": "1F555",
- "digest": "e38f9fc4f87f12ee602dcf2285d59dbc343fc0fc37662992cfe9866c20f58e87"
+ "digest": "0a321eaf1bc5db8436bbadac66c45ba257fc98ad4c7569ce3fc6602c824b6d7c"
},
{
"name": "clock630",
"unicode": "1F561",
- "digest": "735954a650791fc38c845c43998023e652d36e55534850e43952878b8804b2f1"
+ "digest": "55a4c5a665fdd38a724e9357a93c55401fcd5f1b13078c25754bd70c3fc4ccec"
},
{
"name": "clock7",
"unicode": "1F556",
- "digest": "2c4244ec4019e9624e6ea5a751bb735ab87bead33b1ea160265c81bba3c2f736"
+ "digest": "6154306545716e865da0ec537ee4f22bfe6c7294502a64a2dcf425c587d0e2a2"
},
{
"name": "clock730",
"unicode": "1F562",
- "digest": "0bcf20e30be1bb23394696770301867e307f8e5014e0ed7d75ed96efe34d625d"
+ "digest": "6925654de642e50f84661f94364a96c87757d73fffe766aacbf4bbd70130547b"
},
{
"name": "clock8",
"unicode": "1F557",
- "digest": "af454047a1765ef1c8355969302a826d4c47f5c61a6ec47fdec3510a8003b0d8"
+ "digest": "9be2d189c7ea56d39fd259f84853d753c1cf33e64f8ed57f86f822d9ae23a1ee"
},
{
"name": "clock830",
"unicode": "1F563",
- "digest": "e48b81dac055dc6d5f7832cf34368329c573d03b35bfe076fed1c6e6d48a82e7"
+ "digest": "16878613c0000d2f558c88d080551f424a8bd9df1358e0f931dd25c3da68f2d9"
},
{
"name": "clock9",
"unicode": "1F558",
- "digest": "f2a3d1bc029dc0e6406cdaa96542e77503e4cfb79d99c69cb454b8cf635a73fc"
+ "digest": "1d1e7e3c9d085ffa5b7c0f3d9fd394b734f16ae3b60df09af50fe6c8d4f3c8bb"
},
{
"name": "clock930",
"unicode": "1F564",
- "digest": "bb1b2b83052e8e6fb97c48c13bce0d950907e044eb2dabf21d7fed321f75110b"
+ "digest": "9fdef6a4939315c017b165e1dbac7710fb335df8c309be3fe2a011ef7fc28d74"
},
{
"name": "clockwise_arrows",
@@ -1527,102 +1527,102 @@
{
"name": "closed_book",
"unicode": "1F4D5",
- "digest": "afd6dae5fa0f59330fc2adb922e92b3410a33a80a2667651718c7dac588010bc"
+ "digest": "b18288629d201bfdfc5d66ec47df89809d00642b15732757e6a04789f36a7d9f"
},
{
"name": "closed_lock_with_key",
"unicode": "1F510",
- "digest": "d0ed5c00f939111ce86f9c741b733b22e04ebbd871aa33da3eb0f46a6f38b707"
+ "digest": "e39adfe9b30973bca16472c2b7e6462b064a93b9d452aa48edd74c727641a83d"
},
{
"name": "closed_umbrella",
"unicode": "1F302",
- "digest": "3ef08b299f9170007a5433fe82d0953bf0f75b6685d0ce58972f9af032dc471a"
+ "digest": "2cc0592c74601f7439e88c3c1ec4f05e3459608ef1ea6558c5824ed7c3889727"
},
{
"name": "cloud",
"unicode": "2601",
- "digest": "d1e7932551e85c6e86bfb3b41f0c936a6d0953bf9f9119b8cca3eaed22ac0c01"
+ "digest": "5b3a19718dfa8a381929665afdc2284464d24020c8dd0caff4dad465a1f536ba"
},
{
"name": "cloud_lightning",
"unicode": "1F329",
- "digest": "fc9c85cc95f9c456635692c974f72b6d40e14943824b8129a21c47265c3416f4"
+ "digest": "2b32f6d87726df2935ad81870879ccec30ce9b4fd5861d1a6317f9eca2f013d9"
},
{
"name": "cloud_with_lightning",
"unicode": "1F329",
- "digest": "fc9c85cc95f9c456635692c974f72b6d40e14943824b8129a21c47265c3416f4"
+ "digest": "2b32f6d87726df2935ad81870879ccec30ce9b4fd5861d1a6317f9eca2f013d9"
},
{
"name": "cloud_rain",
"unicode": "1F327",
- "digest": "f4406e62ed98f6141ab70736f6d5c540023e805396db0346ee6b7082c3f5e8e2"
+ "digest": "1e1e8bc59e168e1d2e72bf11f2d43cb578cbf0a5f1daf383bba5c56fb750ee71"
},
{
"name": "cloud_with_rain",
"unicode": "1F327",
- "digest": "f4406e62ed98f6141ab70736f6d5c540023e805396db0346ee6b7082c3f5e8e2"
+ "digest": "1e1e8bc59e168e1d2e72bf11f2d43cb578cbf0a5f1daf383bba5c56fb750ee71"
},
{
"name": "cloud_snow",
"unicode": "1F328",
- "digest": "948990cd13dd927917208c026089519fcf8e258a8a284684ace67c9a2f9a8149"
+ "digest": "2d364f859b83e684213e8eece1640208d80a8de0a49d0fc8e0e24c5a8493a3b1"
},
{
"name": "cloud_with_snow",
"unicode": "1F328",
- "digest": "948990cd13dd927917208c026089519fcf8e258a8a284684ace67c9a2f9a8149"
+ "digest": "2d364f859b83e684213e8eece1640208d80a8de0a49d0fc8e0e24c5a8493a3b1"
},
{
"name": "cloud_tornado",
"unicode": "1F32A",
- "digest": "44753516d0bd05d47cfa6eb922aba570ba6a87f805f325772b2cff071460ead1"
+ "digest": "7cbed2343c280ba3996082b3d0fb9d8cd57d6e62fe6c9ecb159f46b4a2e49151"
},
{
"name": "cloud_with_tornado",
"unicode": "1F32A",
- "digest": "44753516d0bd05d47cfa6eb922aba570ba6a87f805f325772b2cff071460ead1"
+ "digest": "7cbed2343c280ba3996082b3d0fb9d8cd57d6e62fe6c9ecb159f46b4a2e49151"
},
{
"name": "clubs",
"unicode": "2663",
- "digest": "5fd19fadd3b0887a6a59819ffbbe33a061055c043200700c31be30e14a5d36d5"
+ "digest": "b8cf72ecd8568ced077b475d94788fb282bdb06d25031b5d54dd63e25effb138"
},
{
"name": "cocktail",
"unicode": "1F378",
- "digest": "cf096ebe15b4053702d490cd96f04d565b4993529bcd6d8d50cb821200d1cd92"
+ "digest": "3792def2cde885cf32167f04904d3b0b788388e8af410c63e4cd31550feba775"
},
{
"name": "coffee",
"unicode": "2615",
- "digest": "6ea6128e353d9f74aee99caaaaa30c53f996fb242bf3bffb0fa92e6b4d373e57"
+ "digest": "0d29615a7a67d3aafa257b909bb915dc74fa8f854acb0d9a2c29e94eedf80326"
},
{
"name": "coffin",
"unicode": "26B0",
- "digest": "b59772d7aa262c4d7433f9cdf76d50011f4c63421b730c8ab4a08675f730c39f"
+ "digest": "78eccc1aad2a822649fba8503d4d30354bef367c4271193c40ddb692308f9db8"
},
{
"name": "cold_sweat",
"unicode": "1F630",
- "digest": "f0d0057bf01db8d930f6e4632c5bf8d0b1bc709bcfb6463a1f1973b5f1d70a83"
+ "digest": "f53aab523ed3fa2224a16881d263fb5e039f163380f92feb2c63c20f9b14dcd2"
},
{
"name": "comet",
"unicode": "2604",
- "digest": "00252ec55d1846d95c8d4c704b35251232d9810029fc215a7da08262dd1f3541"
+ "digest": "40ce93e55c6e57a88d80670b37171190bd5ffc87b7078891d8de5b15795385c5"
},
{
"name": "compression",
"unicode": "1F5DC",
- "digest": "432fbe66e5e3c38ebfeb4eb03465667a1e1be868b4afe510ec95eadda6481bde"
+ "digest": "c8841f7afb5345f1c31da116a7fb41d07232ea58d3f7f1a75c5890aa1a80bfd6"
},
{
"name": "computer",
"unicode": "1F4BB",
- "digest": "99777be010488867c7872b2e235be7c35b1a6f28d92baa921b61ced5491c0257"
+ "digest": "c970ce76b5607434895b0407bdaa93140f887930781a17dd7dcf16f711451d93"
},
{
"name": "computer_old",
@@ -1637,237 +1637,237 @@
{
"name": "confetti_ball",
"unicode": "1F38A",
- "digest": "e77d0c0970d3d12e123e548639fc0fa3ce41668667e4be55baefc09dfaa22cb0"
+ "digest": "a638b16f1acdbcf69edf760161b1bd7ff1fd5426c5b1203ad9d294dcc0701f10"
},
{
"name": "confounded",
"unicode": "1F616",
- "digest": "0f51db64149151d3d7ae5dce08c9af3d064123524fa36fe1f51a78cbd966b6ea"
+ "digest": "e2ff3b4df65d00c1ca9ae0cb379f959ea2cecefb3d676d4f8c2c5f2c103da4f6"
},
{
"name": "confused",
"unicode": "1F615",
- "digest": "ed23587432c1be98356156784ca4fe0b374b7b3b371660d45cfb0a1efd44e322"
+ "digest": "118d7f830ec08a3ac4b798eebb77a989b8c142f2588727181be4a2548e3c4f06"
},
{
"name": "congratulations",
"unicode": "3297",
- "digest": "2a46d640bf24fd4dc7649baf4b28c4adb30eda8d24d70eda07036c85b48195e0"
+ "digest": "02fd1338c54fe5f9a0fd861f23c56edc1d39bcd3140b68f0f626f9e2494d2d1c"
},
{
"name": "construction",
"unicode": "1F6A7",
- "digest": "73fac9fb5eb91954b0f998f9d05fb953241eed988c134fa42477393159fa34fa"
+ "digest": "c3a0401331111b9eda1206bee5f322db80b0870547d307b10dcac1314e4078c8"
},
{
"name": "construction_site",
"unicode": "1F3D7",
- "digest": "0ff52e6adf1927d356b27be5fef6bad2ad842be05e3a0bd16a17efe78e5676d9"
+ "digest": "c611f0a5de10f000a0756935f226845c7292f19ff5581d1f7a7554316338bbcb"
},
{
"name": "construction_worker",
"unicode": "1F477",
- "digest": "2be436fa7ad0a31e328fc6f776044bd1eec35c99541ced891792e3bef738d0a0"
+ "digest": "8c094733987e7c4da8d3aa4588b530ae07042bd70cf337b1fd412a70ee8f0ed6"
},
{
"name": "construction_worker_tone1",
"unicode": "1F477-1F3FB",
- "digest": "172cebc84f91237a85292c5ab0a105cc3abbb96e7423c4ae81feffd00bdb3b26"
+ "digest": "fcd927405fef4486105cd3aff62155467d21cebbc013924d4b52b717b566602b"
},
{
"name": "construction_worker_tone2",
"unicode": "1F477-1F3FC",
- "digest": "3e9b96ddfd639eefda99ad3a0ad26a28a0f2c8be72988c2bdbd648e6104638b6"
+ "digest": "d1ec773828936c703dd6e334e696dc3cf7c34c0a8ec691564a384b735cdeaaba"
},
{
"name": "construction_worker_tone3",
"unicode": "1F477-1F3FD",
- "digest": "11f83c565168dce5ac2387b873769d85ec4087171d6e92fc766c209ea06cd4f3"
+ "digest": "37c114d6879b9b32b800b0d4cf770dcbe04d1455698130ecd709a0cb9dea880b"
},
{
"name": "construction_worker_tone4",
"unicode": "1F477-1F3FE",
- "digest": "09e320e78e3a2940f0c5a0ef9a235ab72c51e053fd8ff433843fdb62571c8e70"
+ "digest": "5264996c1bedb6061a0dfdddce233d863bf308d27127ad152b63bfd983162cf7"
},
{
"name": "construction_worker_tone5",
"unicode": "1F477-1F3FF",
- "digest": "7ac2a1a0038e7aefea889380be604a98255823587e90799165f7db39dd03a0cc"
+ "digest": "87051aec81fd5dfd4dc44ff0411a528ee08253e9494d37efa550694e28dde6d3"
},
{
"name": "control_knobs",
"unicode": "1F39B",
- "digest": "9f10e578b410ff6aa7cc7fe806a0f1181893765303c0ca3867b652f1392a8a22"
+ "digest": "0d7f33ff7acc1cc3a81e6a786ff007df20da145e3070f338505dfed5100e9fcb"
},
{
"name": "contruction_site",
"unicode": "1F3D7",
- "digest": "0ff52e6adf1927d356b27be5fef6bad2ad842be05e3a0bd16a17efe78e5676d9"
+ "digest": "c611f0a5de10f000a0756935f226845c7292f19ff5581d1f7a7554316338bbcb"
},
{
"name": "building_construction",
"unicode": "1F3D7",
- "digest": "0ff52e6adf1927d356b27be5fef6bad2ad842be05e3a0bd16a17efe78e5676d9"
+ "digest": "c611f0a5de10f000a0756935f226845c7292f19ff5581d1f7a7554316338bbcb"
},
{
"name": "convenience_store",
"unicode": "1F3EA",
- "digest": "1ff4351e4a4503f58ed5d35074a2112c681337e35ffe55332187481685573606"
+ "digest": "975dcf9b8e9e3fb1e29574b41300b9d96fd64703b3c18ff52f9f1875d1cf1b52"
},
{
"name": "cookie",
"unicode": "1F36A",
- "digest": "5c78ce2e721b0a3767d6ce0b59c1e88fdf94a7edc94e98c4d6b7aadb5b2aeea7"
+ "digest": "4bed3522bd50091ac5b68ca760661eb484d7f1b9c9d564d2097bd812b7f28ae4"
},
{
"name": "cool",
"unicode": "1F192",
- "digest": "54a96697a5070388ce8364a5ee2e0d78a53acc8b4f6755b1359fd67252cc41e8"
+ "digest": "5739a37341c782a4736adfce804e12776ae33081098a3d052d8ae9a64b4d22d1"
},
{
"name": "cop",
"unicode": "1F46E",
- "digest": "16bee252c2a133bcf57f6d7b8372a61364744a2f662acb90e2005732555135fa"
+ "digest": "78996521bbe231d03ebea355226d8a1515f47cde7b2fbeca1037e7b7e5133466"
},
{
"name": "cop_tone1",
"unicode": "1F46E-1F3FB",
- "digest": "2fc52f3ed735e327d12dadb15f9feb7b7f720fc6857b551548a2a84809053817"
+ "digest": "8a38cd107f5f4c0b821ac43f32df5dc57facaf39fbafb98483ec00fd7df41baf"
},
{
"name": "cop_tone2",
"unicode": "1F46E-1F3FC",
- "digest": "6208f3174ced4f07ba3820ba838b247d7438d69d86eb04927333e7436e56af7e"
+ "digest": "8ab8ab086f3ff82aa4bf4760c3c822846ec2696c41d21dffdac12d5afbe398b7"
},
{
"name": "cop_tone3",
"unicode": "1F46E-1F3FD",
- "digest": "2427d30bdfe127be4d8c3870472cae191eece142c784a5c2809df938f43e7c53"
+ "digest": "fce710a99fd44a7c8af3ea01b2007e46d3ff38d7a0dff1ef26d6f893ede7e6d2"
},
{
"name": "cop_tone4",
"unicode": "1F46E-1F3FE",
- "digest": "6e73f8abdf816f3cb2728b971a5a8d006a236c1d71b2ee1788ab60329f406323"
+ "digest": "3017dd73ef475379911c5e6c79bd0f9f533dbbc5057bce6a11244faa12996ba0"
},
{
"name": "cop_tone5",
"unicode": "1F46E-1F3FF",
- "digest": "4b146465cc95ade7e9ca722e31a1b06311214dae8f7f4d95c6329d56c45b451f"
+ "digest": "a3b8807b3f2a8d6ee9bcec0339355bda486e8c930f727139f5447a4b046a6307"
},
{
"name": "copyright",
"unicode": "00A9",
- "digest": "8143583821085dfc8ac21079fe220288ba3a3b6ca3014dc5dc98b18da77589c1"
+ "digest": "cc28663cdd3f8333d9bb57b511348cde4e51bda19cf0629dccb05c8fc425e079"
},
{
"name": "corn",
"unicode": "1F33D",
- "digest": "0160502226b5f9af81763545f288dbbb20632039d7509f347c751cfdb49dc5b5"
+ "digest": "a099a0b291fa758690e6ee6c762b9ade9a0e3350a707c52d968dfffbcc467de5"
},
{
"name": "couch",
"unicode": "1F6CB",
- "digest": "a93fffed194b404200495abda8772bb35539cfc8499eb0a9bf09c508afad6676"
+ "digest": "84cd734dbaa7f9f519438036d687e7a53217130779bc3de30258f163521b9474"
},
{
"name": "couch_and_lamp",
"unicode": "1F6CB",
- "digest": "a93fffed194b404200495abda8772bb35539cfc8499eb0a9bf09c508afad6676"
+ "digest": "84cd734dbaa7f9f519438036d687e7a53217130779bc3de30258f163521b9474"
},
{
"name": "couple",
"unicode": "1F46B",
- "digest": "97fe611a613216a1788f9bd88a9deb4714ee123a66b5fd3d0ac916fbb4da7304"
+ "digest": "c897ba76e24e2f43a4aa261c2754800a8473f43c7ce53f9909a6af2c4897732a"
},
{
"name": "couple_mm",
"unicode": "1F468-2764-1F468",
- "digest": "3ae6fbf3ba168256ea85c756ac1e7b83fdb8b780d33f06128ed80706ff627eea"
+ "digest": "c812471d35d46e12270653039a907d1dfa2dea0defd65596283e5b8e03cea803"
},
{
"name": "couple_with_heart_mm",
"unicode": "1F468-2764-1F468",
- "digest": "3ae6fbf3ba168256ea85c756ac1e7b83fdb8b780d33f06128ed80706ff627eea"
+ "digest": "c812471d35d46e12270653039a907d1dfa2dea0defd65596283e5b8e03cea803"
},
{
"name": "couple_with_heart",
"unicode": "1F491",
- "digest": "d9701173a5e8dff052ab6a15a42494dbb61dc7146d3734c82916abc9c05f76db"
+ "digest": "420bfa81bad10365550c77a98e1c07eb00d03663fe7b610fab1aca8a0a9d201b"
},
{
"name": "couple_ww",
"unicode": "1F469-2764-1F469",
- "digest": "d2a2ec29c1a1234ea0aa1d9fc6707cf8be8bb36ea8b92523ffa1c3071bcf0b06"
+ "digest": "7ac49153a612d63302299eee996308b7dcafa0a152473dab679215036fe6567e"
},
{
"name": "couple_with_heart_ww",
"unicode": "1F469-2764-1F469",
- "digest": "d2a2ec29c1a1234ea0aa1d9fc6707cf8be8bb36ea8b92523ffa1c3071bcf0b06"
+ "digest": "7ac49153a612d63302299eee996308b7dcafa0a152473dab679215036fe6567e"
},
{
"name": "couplekiss",
"unicode": "1F48F",
- "digest": "e722730de82397da7c8f88d79319b391e8f01fbe4a9133850cc92ad34e77bd82"
+ "digest": "1acfef9d375c4c1deb235babd856b0f90ad4f3194751694cb6abb44f00f29e42"
},
{
"name": "cow",
"unicode": "1F42E",
- "digest": "dcc1efef2f02588806a156ed43da959c587d4c576ff6badec77f820ed3ba507f"
+ "digest": "d71c854ff8b343ee24b8c2b9d56c7cb3fc6fa1a6dc0d7a137841b9f646e6d71b"
},
{
"name": "cow2",
"unicode": "1F404",
- "digest": "dcf59f92fd0a37b2ca720bcda606defa4357b58d8f4ad15c1288ad8d814b2bc7"
+ "digest": "e7a5131d7dee0f3356814b0ac1ea8ff280b12a7b580181e20ddb0b7eeb7e7339"
},
{
"name": "crab",
"unicode": "1F980",
- "digest": "59d34a4e92326ebeab188d9e33b25c20f4d54d187c274713fa3256b03b9e662a"
+ "digest": "e6be16699fdb5d87f42f28f6cc141a44b7ffd834ecdd536813c4b5b86d3fc4a5"
},
{
"name": "crayon",
"unicode": "1F58D",
- "digest": "0f3351c2e68a8d47d27b45a9901be6160de0f9a291bd8680df84d0fc679bcb31"
+ "digest": "b180d6afa4777861222a4228164ce284230fe90c589f52ffa9351bac777e901a"
},
{
"name": "lower_left_crayon",
"unicode": "1F58D",
- "digest": "0f3351c2e68a8d47d27b45a9901be6160de0f9a291bd8680df84d0fc679bcb31"
+ "digest": "b180d6afa4777861222a4228164ce284230fe90c589f52ffa9351bac777e901a"
},
{
"name": "credit_card",
"unicode": "1F4B3",
- "digest": "708c0e7008e06e5d1b3b4e68a7e0ada9f4ae22ab6c28285d81a340f913fd9a84"
+ "digest": "808cd120fd3738eb2be1f6c6c029d98387b0e03fca7d1451e8fbf9c5ab3f643f"
},
{
"name": "crescent_moon",
"unicode": "1F319",
- "digest": "0959f838a410e8bfeebf00aa9658df56e515dbd2361142021071e17244662bfc"
+ "digest": "042e7e01e6e88b97a763b7cc41e2a2b3fe68a649bacf4a090cd28fc653baf640"
},
{
"name": "cricket",
"unicode": "1F3CF",
- "digest": "00eb11254e887c71db5e8945ad211e9e0280f1e02f4b77a4799b64bba2bbe9b3"
+ "digest": "4c4559d0b4efe24cc248fa57f413541307992e519d0cb9fb8828637ac2f4cc16"
},
{
"name": "cricket_bat_ball",
"unicode": "1F3CF",
- "digest": "00eb11254e887c71db5e8945ad211e9e0280f1e02f4b77a4799b64bba2bbe9b3"
+ "digest": "4c4559d0b4efe24cc248fa57f413541307992e519d0cb9fb8828637ac2f4cc16"
},
{
"name": "crocodile",
"unicode": "1F40A",
- "digest": "99abcb42264d40d2450aaca8c3759a019bfd600a311cf3027243f1ca200d4639"
+ "digest": "59cb4164c50b6bc9ae311ce6f7610467c1aaafa848b5fff7614f064715f91992"
},
{
"name": "cross",
"unicode": "271D",
- "digest": "a6e3c345cf6aa2ce690b66454066b53ef5b1dab2ed635e21f1586b1dffc5df42"
+ "digest": "a6b07c838fb75ef2ebefa2df6005e8d784753239ec03c37695a13e3b1954d653"
},
{
"name": "latin_cross",
"unicode": "271D",
- "digest": "a6e3c345cf6aa2ce690b66454066b53ef5b1dab2ed635e21f1586b1dffc5df42"
+ "digest": "a6b07c838fb75ef2ebefa2df6005e8d784753239ec03c37695a13e3b1954d653"
},
{
"name": "cross_heavy",
@@ -1902,157 +1902,157 @@
{
"name": "crossed_flags",
"unicode": "1F38C",
- "digest": "d4da057db289bec83f0106a94c89bd0cd9b52c7c7f8bc69bc8cbce480d53e12b"
+ "digest": "2841c671075e6f1a79c61c2d716423159fb0bc0786e3fb0049697766533bf262"
},
{
"name": "crossed_swords",
"unicode": "2694",
- "digest": "f159978583fa77c73ba6de85d35c4195cbd55963e537bd2bfd8f98ab8ff3559a"
+ "digest": "3771a5b26b514236521ce44e15f7730fa9148c6a782b9b600ab870a1f7de6f9f"
},
{
"name": "crown",
"unicode": "1F451",
- "digest": "e6fe2a28b7d80749ca121cabbe89321dcecdd760a122e73fb1562ea9bb40e90d"
+ "digest": "6741e58d8f823194e0a3484ac1563e20d9e0b44c1bc46d82444dfffa092cdfc7"
},
{
"name": "cruise_ship",
"unicode": "1F6F3",
- "digest": "90519c46ddfb63e71bc76661953da9041e5f0b97e9f8a7a8696518b4d529f3dd"
+ "digest": "2b7b62db5d118a632673564099e3405ea6d61ea9b8e123b5a2aaf011bb2a54a4"
},
{
"name": "passenger_ship",
"unicode": "1F6F3",
- "digest": "90519c46ddfb63e71bc76661953da9041e5f0b97e9f8a7a8696518b4d529f3dd"
+ "digest": "2b7b62db5d118a632673564099e3405ea6d61ea9b8e123b5a2aaf011bb2a54a4"
},
{
"name": "cry",
"unicode": "1F622",
- "digest": "2d6a096796222c29b050f74db6b5aff9b9f61390c5eb56e45d1801918751002f"
+ "digest": "fc3307ec4fe75539770c1123a0e8e721d9e021009a502655132f68d7cc453816"
},
{
"name": "crying_cat_face",
"unicode": "1F63F",
- "digest": "df057d4e3e5c5c87caedf87ea3a6f936811b93f228f46bb7018d2bb5afaa6d35"
+ "digest": "4942c24935c22babdcb8af41d2c0a7588356b6b674bc238902e2f10ad03e2c5b"
},
{
"name": "crystal_ball",
"unicode": "1F52E",
- "digest": "7de438f88134c32c4db67d705e5fecf2a6187a87f56ebbb5bcc5ba09626e2935"
+ "digest": "05f73b30b1e5b0fc66fb5dc6caddd2d547ee7b9d2f97513dc908ba1a2e352e30"
},
{
"name": "cupid",
"unicode": "1F498",
- "digest": "7cb3f7d1ddf9678982197ef0e65735fb465ae8e3652d611f37d3bcccf4d7e2c1"
+ "digest": "246e71f44c6ebc2e4f887e25438e4f894e8cc92e06069e711b893ff391abb658"
},
{
"name": "curly_loop",
"unicode": "27B0",
- "digest": "881a43ae406cb74b2ef136bf970db9928bcdc3bbbb7393e90d2c597fe1dd9a96"
+ "digest": "9e4eb98d6597888f91208080c6a79824adb432ea34f46c85da26cb630bd1cc73"
},
{
"name": "currency_exchange",
"unicode": "1F4B1",
- "digest": "c4d76e9e61fac8d3c0cb9e07f1fbf1a7fcac6f4d4c78776ff7f04fc9391ce689"
+ "digest": "b85377265b9876888969aa42b65bba0be523a370175baf226f20131e535af554"
},
{
"name": "curry",
"unicode": "1F35B",
- "digest": "ebe41ee864c873e3a371888c0087b11dbcb124335812895002ed81fe2b6ba571"
+ "digest": "a01c0a713662817720b485f7739f57e61afc025f5c43792f4de961c94f92f31e"
},
{
"name": "custard",
"unicode": "1F36E",
- "digest": "afc192f405c30e2d529ec0f4b31a7faf474bcd01fded5294dc38880b8bb22155"
+ "digest": "85c2b9ac904134a6c3587eb0a0806f2ab4282c5ed5c79d41734f3203998f757e"
},
{
"name": "customs",
"unicode": "1F6C3",
- "digest": "5abb98151a79cebc1032c0ea149617093e42f41e50574a790a91074cabaa4c3a"
+ "digest": "eb2546e1e617d4c1a1f614318af5e5dacf3e8d9479ffa08108977defa83ded32"
},
{
"name": "cyclone",
"unicode": "1F300",
- "digest": "ae77e15bf2f312f03dbc5c7813d304005bbb549953482db9beb91810c585dc0e"
+ "digest": "7a0f8564d76adf2d0ed272f56dc0d01fb7b557852e0ca797e73f5472b8630bf3"
},
{
"name": "dagger",
"unicode": "1F5E1",
- "digest": "377060a7ce930566a4732b361be98e8a193a546846dfbba2a00abeeef41d1976"
+ "digest": "35a179168198d03295e626cc27d3b92d30a732c55a2ca75d7a11a0fbed414772"
},
{
"name": "dagger_knife",
"unicode": "1F5E1",
- "digest": "377060a7ce930566a4732b361be98e8a193a546846dfbba2a00abeeef41d1976"
+ "digest": "35a179168198d03295e626cc27d3b92d30a732c55a2ca75d7a11a0fbed414772"
},
{
"name": "dancer",
"unicode": "1F483",
- "digest": "e050db55afbb968e02219a58c7e82b824848d299a4df64f0d08d4e1872816203"
+ "digest": "66ffa86827e85acae4aa870c0859fe3a9dad03d21ff4bc800b61c95c902a8a90"
},
{
"name": "dancer_tone1",
"unicode": "1F483-1F3FB",
- "digest": "350f6b2e4589fdd436173163035621b8da0bd49c7b9ec9f39593aae5e0ed0641"
+ "digest": "bdbee740addc890e369d3469a3585eb0d1e4fbc7e04dd6f6aca762d8aeee6a8c"
},
{
"name": "dancer_tone2",
"unicode": "1F483-1F3FC",
- "digest": "a9efc84ec80582f286147ca34162a27fd5989f4030084acdbc309d4368660f5b"
+ "digest": "9f7b4c627241eaa2def9717a5286a423f0b9c1b044dd9ea4442a76f1858d14a4"
},
{
"name": "dancer_tone3",
"unicode": "1F483-1F3FD",
- "digest": "ef187f44278fdb8605c80f5cf199e0b3de8a49085dada2e215bb91e1d7d3be5d"
+ "digest": "a6bd49a377ce6c2004bf126b6f66d0b21d8c14103c2add7b10f12ed9e1c2d302"
},
{
"name": "dancer_tone4",
"unicode": "1F483-1F3FE",
- "digest": "5195bc352dc9d24cc5505a167c756038e55c05048c61799ea1bfdf2debe44ac2"
+ "digest": "4ec2a7629c01b0e9006b5cda4deae3bf297ce3b71d18063f93eeb5c14be19a1a"
},
{
"name": "dancer_tone5",
"unicode": "1F483-1F3FF",
- "digest": "55cb7eee9fa11a16a3932800a19e334546f7396df6aadde22e58fe3185926b16"
+ "digest": "2b48e3a6b366c6f55f73b816e6fb03c39e9890f586f7e9c9043cf0c013d9cdd5"
},
{
"name": "dancers",
"unicode": "1F46F",
- "digest": "39e7dfd9dafeee20f2968960b1179ee4bf3f2b63a3035fc1944024d0ae8b5de1"
+ "digest": "12be66ed19d232bb387270f40bece68bd0cb2342b318f6c9bb8b49c64ff7d0ad"
},
{
"name": "dango",
"unicode": "1F361",
- "digest": "2a1b50abe5dc72335344878d9b701028ccad651964d9e3affeedbf3c2bfd652a"
+ "digest": "34e8cd153c50f2d725abe8934c35c96a3ab533f0cc5fbb1e1474eafad1dc1fc2"
},
{
"name": "dark_sunglasses",
"unicode": "1F576",
- "digest": "6bb1e911a93d5eb0581d3ce8f8929125d3d8fc04e086f3263cfd25af1348ce6c"
+ "digest": "d0a735ad5bf0ece00af2a21abf950b89292ebd8ca6e28b1dbb1368252fb44afe"
},
{
"name": "dart",
"unicode": "1F3AF",
- "digest": "6f28741543a4c1eead21856128ffea1fcf772954fe6af40844dfde47f092ed32"
+ "digest": "998642f06a875905e0a6bf30963c025baff1cf55b8e76884b9119f2d71188b0c"
},
{
"name": "dash",
"unicode": "1F4A8",
- "digest": "25aef37611f1c2f2e96518bf8aeba80580dca9634c8505d390c147388adf6746"
+ "digest": "f7aae7d3887c67d76f3329c2dc9e6807dc580a4b07ab35599c7805e41823a345"
},
{
"name": "date",
"unicode": "1F4C5",
- "digest": "de591b8fad608be761b839beefe9e4c2316320bcf0c44c543a1bc4b89923d938"
+ "digest": "d0b695e4a7cfbbe71b4fbebf345b66ca98f0cf1c751362928e54c23ca78d4c7b"
},
{
"name": "deciduous_tree",
"unicode": "1F333",
- "digest": "ff31a52096ac1eae770f7f71b6d802198add2c8b4d9d7c9327071b6d6ab86c7b"
+ "digest": "3c70f1a77f2754f41c830e88d43b7d53c14311d64626ded164aa9ac7d2695790"
},
{
"name": "department_store",
"unicode": "1F3EC",
- "digest": "c1e200d5fdd792121acabdb17bbcfe8e28a63757cfd895c72d4909f14de95ac2"
+ "digest": "4be910d2efe74d8ce2c1f41d7753c8873579faca83fcf779a4887d8ab9e5923b"
},
{
"name": "descending_notes",
@@ -2062,17 +2062,17 @@
{
"name": "desert",
"unicode": "1F3DC",
- "digest": "e45815250bfc5411de516f87efa218874bcda4b0420b4c17182efc22ba0ce80d"
+ "digest": "d4b1a11c5130debe042df6cc2b3389f15c68a5cb32dc1b3a82b78f733d0c9e4e"
},
{
"name": "desktop",
"unicode": "1F5A5",
- "digest": "ba46323e695918e7253f1013cb991efb09790581c74c07c38bc5e10a20b8e8de"
+ "digest": "cde5bfb6c71bb7d663808a3561b24cb5b5560f95f510b40f81250cac1b21933e"
},
{
"name": "desktop_computer",
"unicode": "1F5A5",
- "digest": "ba46323e695918e7253f1013cb991efb09790581c74c07c38bc5e10a20b8e8de"
+ "digest": "cde5bfb6c71bb7d663808a3561b24cb5b5560f95f510b40f81250cac1b21933e"
},
{
"name": "desktop_window",
@@ -2082,47 +2082,47 @@
{
"name": "diamond_shape_with_a_dot_inside",
"unicode": "1F4A0",
- "digest": "4e0e6364b8682dec9a9e20676161c9c9c0faf0a5fdd5402ca2668b18f2bb850a"
+ "digest": "e91323577ab89e95b0fa0b9272ea0c797b76908f24d36992630e9325273a4ce3"
},
{
"name": "diamonds",
"unicode": "2666",
- "digest": "42b13b2ed8e5fc63fbe81263c06cc203ba18a45ed5cc2a4fdbf617d219a0d3b4"
+ "digest": "bf3d9a020afe8aa226db73590bc193a9c2c3e6e642edd2445c5960c3e67cf153"
},
{
"name": "disappointed",
"unicode": "1F61E",
- "digest": "7f1a619fef84960a9f312d17a58aa58105a4f20a4072efb10227892ab22475d8"
+ "digest": "c0f406c6beea0fd1328adefc097d04aa16b72f7a5afa0867967d8ea25d72db17"
},
{
"name": "disappointed_relieved",
"unicode": "1F625",
- "digest": "a389f5e0a4b619dbc406217967fb1f8f3d0e49b3f790e554ae0ececadbf98967"
+ "digest": "c826f5dd4f2f7e5289d720851d4826ab8284d915606c1b152ab229b7fadbba14"
},
{
"name": "dividers",
"unicode": "1F5C2",
- "digest": "bf4c303452a4c0b4986925041dbec5b7e478060d560630b7c5bc2f997fcad668"
+ "digest": "4b2c653b18cf0fa31f1f0ac94a6fbd214ea0d1b0a90a450ab6e169906fc5764f"
},
{
"name": "card_index_dividers",
"unicode": "1F5C2",
- "digest": "bf4c303452a4c0b4986925041dbec5b7e478060d560630b7c5bc2f997fcad668"
+ "digest": "4b2c653b18cf0fa31f1f0ac94a6fbd214ea0d1b0a90a450ab6e169906fc5764f"
},
{
"name": "dizzy",
"unicode": "1F4AB",
- "digest": "d6fba9b906f0eabd46686e416273a2ca6634249374385f2abf7ed284f0eef995"
+ "digest": "d577545c2de42389695447c6ebbfef895f30f0fda84eef45684f9bf4a9c27ff1"
},
{
"name": "dizzy_face",
"unicode": "1F635",
- "digest": "b55e20c1551a2912bb5ec64a66c788c9d6f21594cc1da66032188f3814b03f40"
+ "digest": "7b3aeaffb4e15ccf633b91dda4a44847a1eb28d78ce58b4d171b20a771bde414"
},
{
"name": "do_not_litter",
"unicode": "1F6AF",
- "digest": "126f8c4085e0a8de8241f211f96c3f42c3e3400ea7d8fdf79a14443c3eceb972"
+ "digest": "98b07fbbcdb438d1b8a755869fa2de8e180a77fce359ec830eb46d38ec3e67cb"
},
{
"name": "document",
@@ -2142,182 +2142,182 @@
{
"name": "dog",
"unicode": "1F436",
- "digest": "c7b729de8a0967b1f38c3fa5ded94e77e329588caeaaf43abfd1090f420e62bf"
+ "digest": "3b31ce067b13e463284ce85536512cb1f8cd8b52fe73659f69971d0d6c1dfc11"
},
{
"name": "dog2",
"unicode": "1F415",
- "digest": "e1897ca60bb3d2662cbe7933352e2b9c50739adf5901d3328797bf399575b97a"
+ "digest": "0a8901bce5ed994533ff84299b2a1364de28d872c9f9510d3426a83e8a9d2e34"
},
{
"name": "dollar",
"unicode": "1F4B5",
- "digest": "7db1e57f799439df1295d42b5249393f1e8cacc8df54caf30499c967a7282742"
+ "digest": "52438e38867aedc021740bb41f9ba336e75a50faa148419412a01d75d8c93155"
},
{
"name": "dolls",
"unicode": "1F38E",
- "digest": "398e7ff5780328700aadded7ce8c50757b1096af5cec66cc4d813a6714686b6d"
+ "digest": "a687184e9a0915deef44bb3cacfb19d3f3f19cf2c110f1da90191dd567333c57"
},
{
"name": "dolphin",
"unicode": "1F42C",
- "digest": "27385af08848d93acdd13f72751074c2cbccb5ab3c6047e334598af74ed4862d"
+ "digest": "0b7ee08f4236232ca533ed3a3023d28020d36f178efaec5ce8b0e13a84778512"
},
{
"name": "door",
"unicode": "1F6AA",
- "digest": "3365d7834086328ecbf1da0037f1cf1d0eb49534e173f7962a9e8f4b2ab87e26"
+ "digest": "984a9ca88852ebdb539e0c385d9c6ffe5010e9189bc372a3d00f5c8d44c8e6f5"
},
{
"name": "doughnut",
"unicode": "1F369",
- "digest": "b4b99fdfe8d07b49cbdd78f8c57e4424819a4ffc8a3ba4867da44cbb3b3a5cca"
+ "digest": "27634587e6a53807baa32157bb06b0e115c8ad8aefebba7ebb0b65a084170e3a"
},
{
"name": "dove",
"unicode": "1F54A",
- "digest": "4e2e9c47e5632efe6ccf945d61dbc2f1155a2e52905e17f307b502a2c951bdb8"
+ "digest": "7c665f8594ffa53e72b01647e9d27360fb87d52d02fe9f20fc5fda08f9797dc3"
},
{
"name": "dove_of_peace",
"unicode": "1F54A",
- "digest": "4e2e9c47e5632efe6ccf945d61dbc2f1155a2e52905e17f307b502a2c951bdb8"
+ "digest": "7c665f8594ffa53e72b01647e9d27360fb87d52d02fe9f20fc5fda08f9797dc3"
},
{
"name": "dragon",
"unicode": "1F409",
- "digest": "d7d016568b54d67017681a075fb799d4a2a790ecfa2946d02dbcee629eb4975d"
+ "digest": "2abcb3d945d848e34ffc76203b29ef26df7458856166fffd155611f7bbe72652"
},
{
"name": "dragon_face",
"unicode": "1F432",
- "digest": "4d0025f1df63b62448477a8f08a50704e15caafb10fea476b529113f41797ab9"
+ "digest": "0030548931b931e3b51f26cf660394aee36499e688ba83ce9cfccb635dcd4d54"
},
{
"name": "dress",
"unicode": "1F457",
- "digest": "02d56ed227280eaf5ad92830ee304afb81f74bb5a13c855397bcd04dd7fa51fb"
+ "digest": "96ceba928fb356f7c0ae99bf22552321f08a65d5f1c0340ab89641219ad366ad"
},
{
"name": "dromedary_camel",
"unicode": "1F42A",
- "digest": "5afe8a0b73f9f4560264020b1e02a566149dbc38c15a00d2fb5cd90b32d09a75"
+ "digest": "e06ef69c29f0fb12481727c0b4124e700572d3d7955e173279320f43f286518d"
},
{
"name": "droplet",
"unicode": "1F4A7",
- "digest": "a92c419792cbd3ba90ed21547362134cfac3e17a5304ee4e3872c9f7b561f834"
+ "digest": "6475b4a4460a672c436a68f282ac97fb31e2934db4b80620063ee816159aa7c3"
},
{
"name": "dvd",
"unicode": "1F4C0",
- "digest": "1ba23e2f01ced5e192e4c1d2f766d9bce400470e81c81410139fd3c0739422df"
+ "digest": "3b7903285d91277181c26fdc9df857761bbac509d352e320c2519ea3b132704f"
},
{
"name": "e-mail",
"unicode": "1F4E7",
- "digest": "12135310cfedc091d120426f5b132df82b538c5fcad458bf6b21588f353c3adb"
+ "digest": "39b5a57a2376e4a1137e381be02a1775bd580e0371438f5297a401ea634f1830"
},
{
"name": "email",
"unicode": "1F4E7",
- "digest": "12135310cfedc091d120426f5b132df82b538c5fcad458bf6b21588f353c3adb"
+ "digest": "39b5a57a2376e4a1137e381be02a1775bd580e0371438f5297a401ea634f1830"
},
{
"name": "ear",
"unicode": "1F442",
- "digest": "70ba1103a34e68590d91a3b6f8acdbad3b1c65e46e31e26ee1cb855c1e21095e"
+ "digest": "4fdeb5a46e69311ecfd09c5b45c9018c24b625e28475cca8fa516b086ef952f8"
},
{
"name": "ear_of_rice",
"unicode": "1F33E",
- "digest": "ddd5f3cc83dbdafd9115861eecd0128e52165bb1dd0049df06ffc564b650d384"
+ "digest": "2997c340c2b333d6ba9b73f94ff1a1881735fe0cc4f0c72d7719b305499fc425"
},
{
"name": "ear_tone1",
"unicode": "1F442-1F3FB",
- "digest": "72977be94f5d287a09d175f98fba8b7955ae13aa12ce8e029c0ca875c02ee820"
+ "digest": "5ca759b8569a377a4e63e30d94b585b9f76d15348a8a0c1ba19fdc522790615e"
},
{
"name": "ear_tone2",
"unicode": "1F442-1F3FC",
- "digest": "5ff2e46cb3be7f13b8b94092246b58dab4c2a9ee2a5a46e0b84cf35a6928141f"
+ "digest": "12aafb3ef2cfcdc892b2877c2e24920620f0f77f850e12afbfe55eadce9e37df"
},
{
"name": "ear_tone3",
"unicode": "1F442-1F3FD",
- "digest": "19b523f5ada2acaea94b922059c458a3303f4da1dd4c197cf25d31a0e6ecc4b2"
+ "digest": "f4d28d9f72cf116ac92d80061eb84c918d6523bf53b2ad526f5457aba487d527"
},
{
"name": "ear_tone4",
"unicode": "1F442-1F3FE",
- "digest": "6a5cca9f49c539ef7d0883a2f39652f33ee2d3b25dca0234e4ba027ebbb2b466"
+ "digest": "eaa9453670f7e3adc6ec6934ee70efc9bf60fe6c99c5804b7ba9e3804aec65de"
},
{
"name": "ear_tone5",
"unicode": "1F442-1F3FF",
- "digest": "a0a56e8abd36e9be6e2448bcee6f56ecb8bf62d728b19ab6e8f9c6338e226b67"
+ "digest": "54bd0782419489556b80e9e0d15b05df74757aa4e04ba565f45c20d3dd60e3f1"
},
{
"name": "earth_africa",
"unicode": "1F30D",
- "digest": "d4921b543d7cf0c7344fa50c5e4d5a76c208d900be852adc1ee82ed4e8861a39"
+ "digest": "c691a6f591f5a07b268fd64efe113e81cec8d5963ad83ced2537422343ff7ecf"
},
{
"name": "earth_americas",
"unicode": "1F30E",
- "digest": "61691e6aa9b8d90fc7f75fbc6cc7add5c36022d38f3e05c9d7c54dc44cf865bb"
+ "digest": "a9c60cf8341ff59a9cc1a715b7144af734fcd28915a8e003a31ebf2abf9aedb1"
},
{
"name": "earth_asia",
"unicode": "1F30F",
- "digest": "262904cb552c7f5cf828a11071b3d430a74824b7464e8759ef93ee23b1705767"
+ "digest": "ee2beb61fb8c87279161c5a8c4ad17bb71ce790123f8fa33522941d027e060a5"
},
{
"name": "egg",
"unicode": "1F373",
- "digest": "a7dd617cad489c481ffd14937d9ed491cdd5756903e00473f42600c2fbefb600"
+ "digest": "563ffd6cae381ce1e318cdacc54e70040d6a01a50d0db8aeb50edbbe413eac58"
},
{
"name": "eggplant",
"unicode": "1F346",
- "digest": "e5402e8ae5b7f9699ed86b97c242f7939d5731c5a364a2d5b9d04ea5d293cda1"
+ "digest": "ec0a460e0cf0e615f51279677594a899672e1b4ecd9396e17a8cfa2a3efe5238"
},
{
"name": "eight",
"unicode": "0038-20E3",
- "digest": "34e293d3228e4643a0132d592f96db91b651fe6ced056ac3c8a3fd49c5ed3416"
+ "digest": "57ff905033a32747690adba6486d12b09eb4d45de556f4e1ab6fb04e1fb861a8"
},
{
"name": "eight_pointed_black_star",
"unicode": "2734",
- "digest": "c3c2da75731a9a0f4f0a8d1f9cffef75c35e19b7f5d4081da33ac12b46be5fc2"
+ "digest": "7bf11f6e28591e3d0625296aaabf4ecb75c982e425abf3049339e93494acc17e"
},
{
"name": "eight_spoked_asterisk",
"unicode": "2733",
- "digest": "cc69618c1074d2b00e6f2c49df5e2c5ff6f4c0fae305505eb8c9daa65a0ea340"
+ "digest": "bb0758e7cc0e357285937671a91489bd32ce9d248eecdcc9c275a53a66325b26"
},
{
"name": "electric_plug",
"unicode": "1F50C",
- "digest": "732e1d1675233a0b4643cb73d0c352f8a5a56a11ee90d26627ad1e43c2e4a8e5"
+ "digest": "b10ce87af86fa4f4022572ceb5ecd73bea867347a86832a7ea248364b0aad8d0"
},
{
"name": "elephant",
"unicode": "1F418",
- "digest": "08df3910c4d5d8f49a72c47dd938195e495bde8fd8b3e7b17098a2c1afc41634"
+ "digest": "b7750f4b013fbd28ac5330e1694ef4d3b4a9c6fc7b807879db0c24b035a16c29"
},
{
"name": "end",
"unicode": "1F51A",
- "digest": "05844ab9dcb43deff86f04617af6ea09215595de1415dcfaae018bced57938fe"
+ "digest": "dd93aee6986eb637a8b58f234da47568b88525599f73246e322af030351997a2"
},
{
"name": "envelope",
"unicode": "2709",
- "digest": "aad272511d0db910437ba25cf1fb9c806d47aad92a232edb87055916daf4676a"
+ "digest": "f5a512022a2f5280f372ff39c22cbda815f698710ca66f8f8c4d08418f98ca78"
},
{
"name": "envelope_back",
@@ -2362,192 +2362,192 @@
{
"name": "envelope_with_arrow",
"unicode": "1F4E9",
- "digest": "c1ba19b5e7cf64c547ac46eee139e6af70700d49ab511a96e6828c30feb116bc"
+ "digest": "f8643212e6a94f58ccf2bcedc54c5fda8ebeab274f4a8803f253de5f50ddb1d6"
},
{
"name": "euro",
"unicode": "1F4B6",
- "digest": "f571952583ffecfa5777065e4d1b680c423d25bc80e567a48fb5d7a1c1b5e735"
+ "digest": "3af3e223e8f26468a94f6f5c17198432656e8d20b3bab31566c2b5a86e717df4"
},
{
"name": "european_castle",
"unicode": "1F3F0",
- "digest": "db82e383975d079a7bb006e7868035088d75c33bd4031cf8466b71089b65426f"
+ "digest": "21082d0be7e3b2794e59ff0170da0cfe42a9b734cf02704603e3b52ff48202ba"
},
{
"name": "european_post_office",
"unicode": "1F3E4",
- "digest": "d9b38e0f0ca3ad8895b40c767bdbb2b142ccaf03a86c2f275f57a31ed478801a"
+ "digest": "02b4c7602939f0cb9cb2b4e05996bcdb6bd93cf8025c2ea02db8cbe13ca397d0"
},
{
"name": "evergreen_tree",
"unicode": "1F332",
- "digest": "60d8b2d86b20255341f7ecad6d0f178ba9db5fa6b3de92f1b439cdb19f2fc0b1"
+ "digest": "74b226098e66c0a94a92e0f22b9d631736e12dca72c34182c9d0ba56aa593172"
},
{
"name": "exclamation",
"unicode": "2757",
- "digest": "cd900ecf82de2b26f0d7783dac4b3232ae94d2cddad5bfacea2eaf65b7ac0a09"
+ "digest": "45b87ae4593656d7da49ff5645fb6a2a18d582553295358da9f09f1ae8272445"
},
{
"name": "expressionless",
"unicode": "1F611",
- "digest": "2ec9466b2d629907ce4c3e24e57f7ee556d2258ff011d972e14d0ae969a40c51"
+ "digest": "34e2a1c8121f4f0bc4ce33d226d8cc1a4ebf5260746df2b23e29eef24ee9372e"
},
{
"name": "eye",
"unicode": "1F441",
- "digest": "790841e8fce647173eec3c5019440ad9c7e916c535f92acb3132bd92df148cad"
+ "digest": "79ecff79c2edee630e72725b54e67ee2e96d24ca03fef2954a56a09c0a2227f8"
},
{
"name": "eye_in_speech_bubble",
"unicode": "1F441-1F5E8",
- "digest": "bcde5a89a7653bff302685d9d632dd2723796a7ac73125fb7b9493d1ca848e0a"
+ "digest": "c0050c026c2a3060723cab2df2603c1c7da7ed81faedb9ebe16cd89721928a55"
},
{
"name": "eyeglasses",
"unicode": "1F453",
- "digest": "fd140bef19c420bafe59368d35dd58a58a53e7145b104bae94be10f90679213b"
+ "digest": "d4a9585d6c43ef514a97c45c64607162e775a45544821f1470c6f8f25b93ab81"
},
{
"name": "eyes",
"unicode": "1F440",
- "digest": "57ed1f87ebe2485ea32ea69abdb8c5f7ccdcc149b33e74230d801f0883c68c5d"
+ "digest": "1d5cae0b9b2e51e1de54295685d7f0c72ee794e2e6335a95b1d056c7e77260e8"
},
{
"name": "factory",
"unicode": "1F3ED",
- "digest": "6e6b35ae013e5dd26852c9a95d05c39e89c1c1950a33f47e7b951c34af18f37c"
+ "digest": "c7aeb61ed8b0ac5c91d5197c73f1e2bb801921c22a76bb82c7659d990680dcb0"
},
{
"name": "fallen_leaf",
"unicode": "1F342",
- "digest": "28ba8628065ffa973b525dd1455691c828d49c2b8c814af387880c13f6707f7e"
+ "digest": "81fce04231d48db0e55f3697f930e9a7e3306bed5e35f1234e98c40a24ac5626"
},
{
"name": "family",
"unicode": "1F46A",
- "digest": "b5307f86e54cfea581e8406f4b95c801e250a893a9d208cc9a69a6d910b90932"
+ "digest": "06f2ce63768ffe43b3d9b2a9660b34d043f37b3c91610dd62343ba21df8ecbe5"
},
{
"name": "family_mmb",
"unicode": "1F468-1F468-1F466",
- "digest": "49a753c3fcd4420800dd1cda585dae6bfa81615ad4862b477246456f86dc9e82"
+ "digest": "41a18405be796699a7eb7c36ab6f7d898e322749997f45387377acf5bb16a50f"
},
{
"name": "family_mmbb",
"unicode": "1F468-1F468-1F466-1F466",
- "digest": "882a3a0048efd666b0ab3a07b9f08041aa3a2acdab02664d0feff30bbfa70d68"
+ "digest": "87255d1d18c6971c8c083c818e598424c1bd717eed892478b7e9516639dbfb45"
},
{
"name": "family_mmg",
"unicode": "1F468-1F468-1F467",
- "digest": "45dd75c19d260a658c8ac93cf878976b96d2000f0efc9c59e72dacc80afb08fa"
+ "digest": "a132b1b8f10b318d8e23aee15dab4caa14528aeb3c89966d4bcc25fb54af72ad"
},
{
"name": "family_mmgb",
"unicode": "1F468-1F468-1F467-1F466",
- "digest": "910f44a348a951d36ee1f1484d237085bec5083c3875a4d908831dfc64530eaf"
+ "digest": "eb2bc1966df406aaf38ce5a58db9324162799cdacf31f74f40e6384807a8efc2"
},
{
"name": "family_mmgg",
"unicode": "1F468-1F468-1F467-1F467",
- "digest": "012e75ad0d1b16c2ce63bf80a1ebfb1fc194229cfaf1241039599b82832f6aee"
+ "digest": "24f3d60f98fbd6b687f7cacfb629390b90509a754036e5439ae5294759c0606b"
},
{
"name": "family_mwbb",
"unicode": "1F468-1F469-1F466-1F466",
- "digest": "049a32f61c54f093d2124e25f8b2ec7eac13161e2f2ebf6dc067797698cbe831"
+ "digest": "2f77692bcb9275c4df501b64a18401dcaf8c68b21f26fbdad59b1feab0c98fd1"
},
{
"name": "family_mwg",
"unicode": "1F468-1F469-1F467",
- "digest": "ba32c637caba634bda99ccba2a1a2a4b6f33aaaed933c30c7d5a51e8de1790d0"
+ "digest": "1a976d13127665d9386cebfdb24e5572dc499bda484c0ee05585886edc616130"
},
{
"name": "family_mwgb",
"unicode": "1F468-1F469-1F467-1F466",
- "digest": "198faba987f45429329b93bbce4f111329f284558bf0eecfa1424186b5f009fe"
+ "digest": "960ec2cbac13ef208e73644cd36711b83e6c070c36950f834f3669812839b7f8"
},
{
"name": "family_mwgg",
"unicode": "1F468-1F469-1F467-1F467",
- "digest": "3fa2e57cba314dcff04cf8186914823e1e081aabf34fa7437b05c58015df400c"
+ "digest": "8353b03dfa5c24aba75a0abdfdac01603f593819d54b4c7f2f88aafb31da0c6a"
},
{
"name": "family_wwb",
"unicode": "1F469-1F469-1F466",
- "digest": "b9592fc110a25a478569075deaa520308ef74579cd47aa44df9836599d68143f"
+ "digest": "07a5dd397718c553573689f6512f386729c13a12d5dc78be47c06405769cd98a"
},
{
"name": "family_wwbb",
"unicode": "1F469-1F469-1F466-1F466",
- "digest": "88f398997835fcf5153f17f6baf0deeb2a9c25ce2f8422192c18ac23e90b3193"
+ "digest": "b627f460f1da0d47b0b662402940b2b77c9538d380d05436dfca4b456c50c939"
},
{
"name": "family_wwg",
"unicode": "1F469-1F469-1F467",
- "digest": "c8d859d3c957fe0d535efccde295fe99bab76e3d28ab5a49c8e736608461cb2e"
+ "digest": "2d6f373bed53f1028f0fbe9caf036465a351f37b9e00fca7d722cc5a1984f251"
},
{
"name": "family_wwgb",
"unicode": "1F469-1F469-1F467-1F466",
- "digest": "006506e4a3d0c82642a0c8481ce95e5e3b969e20fe2def0a16dd686afddbc705"
+ "digest": "72be5c85e1621f73d6794edd6e428febdb366b9e4c816f7829897fd1ab34642b"
},
{
"name": "family_wwgg",
"unicode": "1F469-1F469-1F467-1F467",
- "digest": "2553f0deab133aad09b99411d9dd68b56fede30f55ee1f354358767765e36673"
+ "digest": "c39e0916069460d2d9741bddf58e76f5d6a09254cba0eeb262345adf8630bc32"
},
{
"name": "fast_forward",
"unicode": "23E9",
- "digest": "1baaed10969b60c083da754ee056bb71df36182cc65af40640acfb76f6b39200"
+ "digest": "e7d2d8085cfd406c2b096e8dd147dd3722290a5727b1f7df185989526a2335ec"
},
{
"name": "fax",
"unicode": "1F4E0",
- "digest": "b0a392192d03bd5d1ad5ee8eea933cf64725b1776819537bbed27561d78192e7"
+ "digest": "ff85ffa440c5379c9b138ebe2d7912d6098da3b37a051b80442d5557b7f993b0"
},
{
"name": "fearful",
"unicode": "1F628",
- "digest": "7c4cc4de3357c2a6d6e779342b09dabb3ef832a32f2778a0ba074b446f588e8f"
+ "digest": "b72bdf7d075d5c4e38bbd8512fb45fda2e85c9c8732a47e67575ae9f2ed4c5df"
},
{
"name": "feet",
"unicode": "1F43E",
- "digest": "cae13fb54ec64dbcf86ea25bebe2b79877e2d4f5d810b867f095f1d3dfc7f144"
+ "digest": "45aca538d3a9831a0c7de491e5656c17705c07b8f4ac8e85254656b608976016"
},
{
"name": "ferris_wheel",
"unicode": "1F3A1",
- "digest": "a710a8a0fb039d953313b75330db37e3228d856593547b1f04dc83c00168b987"
+ "digest": "24b4551b7b79a2a5fd73de61542f2b444f896a52030c5f29791c8fcfcc28b95c"
},
{
"name": "ferry",
"unicode": "26F4",
- "digest": "21ea239b5adb68dc1ce6c5a1993b0a0b835ef6cc7a0a27cb890838d8475504f6"
+ "digest": "5002a72af2e3c4cef9a36ad5987aeed7d99f96bfd13e56f78957315ec7e749a3"
},
{
"name": "field_hockey",
"unicode": "1F3D1",
- "digest": "1e46c7f0b5b79c90a5d211ea14cd7e358b1a26a3c8294439253f2b08d0e5c92e"
+ "digest": "4ee091d96161ba719ab8fd6f2b03f96d902a6f22cffe0563b930618bb8ac2b67"
},
{
"name": "file_cabinet",
"unicode": "1F5C4",
- "digest": "c0b7bdab6c98909eb0fbf1ac89da0008bb00ddb1cb57fe64b4a5ac993eeb18c9"
+ "digest": "92914147bf93e6d64271ff99d217a18a9850a367d08a5f9f458ecf9311a5bbe9"
},
{
"name": "file_folder",
"unicode": "1F4C1",
- "digest": "d98f93c6d7283df0c45f08d3d31ecf5b91b6db1b735959f19e42bfada500a0d1"
+ "digest": "62a42a929267cfbfdb795ead381c9657c343458bc5fca95ea8a0ab892c61d4f6"
},
{
"name": "film_frames",
"unicode": "1F39E",
- "digest": "754a0a60e978f8299a0c4f8959e1f9260f01683e15ae943db430036f01a79b18"
+ "digest": "4da212148cadb9c4ea91e60d2d8316e38cea99ef4f14afc023711dd7c54ade5a"
},
{
"name": "finger_pointing_down",
@@ -2602,17 +2602,17 @@
{
"name": "fire",
"unicode": "1F525",
- "digest": "b44311874681135acbb5e7226febe4365c732da3a9617f10d7074a3b1ade1641"
+ "digest": "b3e67c913903d900f5e50e7e7e4d7e9370bb6ceedfbee548be39e4c9e4b69416"
},
{
"name": "flame",
"unicode": "1F525",
- "digest": "b44311874681135acbb5e7226febe4365c732da3a9617f10d7074a3b1ade1641"
+ "digest": "b3e67c913903d900f5e50e7e7e4d7e9370bb6ceedfbee548be39e4c9e4b69416"
},
{
"name": "fire_engine",
"unicode": "1F692",
- "digest": "3ae03fa34a7088ada95458eb4ee3e97691b3489149f6bbc168086f0483ed3bb2"
+ "digest": "c3a518f27d625e3b62dffa227eb82764bf0a147f10ec0e7f4f43f3f96751af20"
},
{
"name": "fire_engine_oncoming",
@@ -2627,507 +2627,507 @@
{
"name": "fireworks",
"unicode": "1F386",
- "digest": "3dee83a27c406960253ca1460eb88a599c7b81506051b69605a421b17fe8282c"
+ "digest": "b62ae08a00c0cc6eba8f9666c8fd9946ce57c3cfc01fe99542a8690a4a566a65"
},
{
"name": "first_quarter_moon",
"unicode": "1F313",
- "digest": "8fa066362d77bd889090bbe0904ca47f34704e29781c67133c6eaa521c3e1972"
+ "digest": "a207ce93084448622a4a5c49c85c566a9fda6be7337c86a013eeb713fe47fd29"
},
{
"name": "first_quarter_moon_with_face",
"unicode": "1F31B",
- "digest": "8877edb366f8eaa00fd83200acf5a17c3b84d246a250519d565dda3aea866ec3"
+ "digest": "1d1f54a5075f2311bcc017c44898b9d8c58edc13b298d58c238fff9ab8ee2ef3"
},
{
"name": "fish",
"unicode": "1F41F",
- "digest": "9ce742108794cc15e59f7719623ae938efbd8155c93ad72585a32f4e32ea9414"
+ "digest": "8f62f08fbeaf39694c19816b5c7d4f292017fe5bf9f8dd7e40f1630f5f83b28b"
},
{
"name": "fish_cake",
"unicode": "1F365",
- "digest": "1b5b14509287e30da9b8d7abcec376b247f9095aea4bf3fc320349f061a4c321"
+ "digest": "5a6ca2100c8830927b22afa6f1d2fc821f5692cd23507fe5a776f6e085cbbfb2"
},
{
"name": "fishing_pole_and_fish",
"unicode": "1F3A3",
- "digest": "35db56776db1fcec7c8479922d57d54da2577cfe44a894bfd78c51c950c450fb"
+ "digest": "f8fb84eccceec88321b0a2a46f732ecfc378f787c19c27ac1327735f1ca9a48b"
},
{
"name": "fist",
"unicode": "270A",
- "digest": "6b80ac2e4d8b830ae06f7c1626d456460094e4ba20c20fb82dabb6b3d2ce7605"
+ "digest": "557f96d85615b8d78436bc67266115bfc8556c97c14f7909dfda1cf134e8344f"
},
{
"name": "fist_tone1",
"unicode": "270A-1F3FB",
- "digest": "d7c79f4f988dd68f064baa5a3a568ab299f8d409db45c8463f39b80e5dd6081f"
+ "digest": "6c1b946f9e01abc39b5085e24e8b6077fc0e34188e8daa30c6a3adddd387413e"
},
{
"name": "fist_tone2",
"unicode": "270A-1F3FC",
- "digest": "d1108194e2d962f9ccd00131876d769a8e003117a460d18b2ccbf93e0a0ea346"
+ "digest": "e9b9e1ec638dca4d5e1519bca7338f58cce2f2a282ee4c3581e8643166fc415f"
},
{
"name": "fist_tone3",
"unicode": "270A-1F3FD",
- "digest": "12f5644b632c95a5c2e41cc9af299e286e266db8b3860091ef5be5f0c4ccc026"
+ "digest": "8c14d24055c143960b3d2a27fe23c55d2d3ac5f84f87e4e876616235e8698c7f"
},
{
"name": "fist_tone4",
"unicode": "270A-1F3FE",
- "digest": "521a3ac573381f3bc37a08ddd2d122767aaa0b6b7a38050d3671a12343351816"
+ "digest": "923f034f481e952e6e5d1664588f99f79bd5416d4197b0ade6621f2669ce5765"
},
{
"name": "fist_tone5",
"unicode": "270A-1F3FF",
- "digest": "604e5a234da1b9160e506b3c9026faf9e04268fced7b44baa1ef5e3d4efa83a4"
+ "digest": "d691d2902216080916a29047e07d7a5bf2aed07e062067ca9d01cbf6fdf48c8d"
},
{
"name": "five",
"unicode": "0035-20E3",
- "digest": "0cbd6cd11eb6c2d67749112750d125f4f0a07b53bb7bfb1de0986d943ea9d632"
+ "digest": "8f03f62fdbf744ae49c8a60fbf715ebfccbd6b62d91148e0923907006f3c2726"
},
{
"name": "flag_ac",
"unicode": "1F1E6-1F1E8",
- "digest": "d9db1edeb709824a1083c2bba79ca5f683ed0edded35918bb167d1ee7396c8da"
+ "digest": "2e5c08535dc8ea96422d56a36b4fffc0b3bd2a13f2ab0d8dbd0e3a29bf3fc40c"
},
{
"name": "ac",
"unicode": "1F1E6-1F1E8",
- "digest": "d9db1edeb709824a1083c2bba79ca5f683ed0edded35918bb167d1ee7396c8da"
+ "digest": "2e5c08535dc8ea96422d56a36b4fffc0b3bd2a13f2ab0d8dbd0e3a29bf3fc40c"
},
{
"name": "flag_ad",
"unicode": "1F1E6-1F1E9",
- "digest": "04a8c1745d9b8b20e903302379f2557e8082f72e33878db4cb2cd6b33eb97952"
+ "digest": "184fdcf790b8e2fd851b2b2b32f8636c595dd289734d12dc01ae4aa177e2043a"
},
{
"name": "ad",
"unicode": "1F1E6-1F1E9",
- "digest": "04a8c1745d9b8b20e903302379f2557e8082f72e33878db4cb2cd6b33eb97952"
+ "digest": "184fdcf790b8e2fd851b2b2b32f8636c595dd289734d12dc01ae4aa177e2043a"
},
{
"name": "flag_ae",
"unicode": "1F1E6-1F1EA",
- "digest": "868324ac2e7bea1547f5de95f39633b77b8d62f3b3433b3d1a4ee96d169a09cd"
+ "digest": "4a3257a9ce118e97567e76280f24d60fb555f1bada2eb26a2442a47f9398d21e"
},
{
"name": "ae",
"unicode": "1F1E6-1F1EA",
- "digest": "868324ac2e7bea1547f5de95f39633b77b8d62f3b3433b3d1a4ee96d169a09cd"
+ "digest": "4a3257a9ce118e97567e76280f24d60fb555f1bada2eb26a2442a47f9398d21e"
},
{
"name": "flag_af",
"unicode": "1F1E6-1F1EB",
- "digest": "9a94458519e9db5d6cf1557e54fdf62d7e48aaf7de25744a093ec8f284656226"
+ "digest": "0f6c719cac7ab3140694f6b580787ecdbf503e38f16de7ec5803f7d06a088ec3"
},
{
"name": "af",
"unicode": "1F1E6-1F1EB",
- "digest": "9a94458519e9db5d6cf1557e54fdf62d7e48aaf7de25744a093ec8f284656226"
+ "digest": "0f6c719cac7ab3140694f6b580787ecdbf503e38f16de7ec5803f7d06a088ec3"
},
{
"name": "flag_ag",
"unicode": "1F1E6-1F1EC",
- "digest": "ea59fabc2bd9024df06a59a34412f52bebfeb03eb6abd73d8fe153e3a68e28f4"
+ "digest": "92bf5a0e74564739862e9ba79331ffa656b7bae2ace0fc8dfd288984e4d510d4"
},
{
"name": "ag",
"unicode": "1F1E6-1F1EC",
- "digest": "ea59fabc2bd9024df06a59a34412f52bebfeb03eb6abd73d8fe153e3a68e28f4"
+ "digest": "92bf5a0e74564739862e9ba79331ffa656b7bae2ace0fc8dfd288984e4d510d4"
},
{
"name": "flag_ai",
"unicode": "1F1E6-1F1EE",
- "digest": "75676ded736ad2ebb921e9fd8ebfef49819a35c3dcf005bbc3b7e8c6e75178f2"
+ "digest": "aeaadc7ffafd8a1e01fdabc69d35f725d5f737b4c284a36191d96729f4e66e8f"
},
{
"name": "ai",
"unicode": "1F1E6-1F1EE",
- "digest": "75676ded736ad2ebb921e9fd8ebfef49819a35c3dcf005bbc3b7e8c6e75178f2"
+ "digest": "aeaadc7ffafd8a1e01fdabc69d35f725d5f737b4c284a36191d96729f4e66e8f"
},
{
"name": "flag_al",
"unicode": "1F1E6-1F1F1",
- "digest": "77b835dcff399b609e2479cbf10f08344c8fc277370ba8e4540165ca15563847"
+ "digest": "5ce7866d214d18c5f3438d480d14e77d104c4de679f0fdfca8cf0a44ce48eeea"
},
{
"name": "al",
"unicode": "1F1E6-1F1F1",
- "digest": "77b835dcff399b609e2479cbf10f08344c8fc277370ba8e4540165ca15563847"
+ "digest": "5ce7866d214d18c5f3438d480d14e77d104c4de679f0fdfca8cf0a44ce48eeea"
},
{
"name": "flag_am",
"unicode": "1F1E6-1F1F2",
- "digest": "3b820c628dd5a93137f7288a43553778f60b0beea4c0a239d063893c0723e73d"
+ "digest": "b40f5705f0cf9ef0fa7ffff0b371c4099319001ce79f894c317912f4dc5de4c8"
},
{
"name": "am",
"unicode": "1F1E6-1F1F2",
- "digest": "3b820c628dd5a93137f7288a43553778f60b0beea4c0a239d063893c0723e73d"
+ "digest": "b40f5705f0cf9ef0fa7ffff0b371c4099319001ce79f894c317912f4dc5de4c8"
},
{
"name": "flag_ao",
"unicode": "1F1E6-1F1F4",
- "digest": "d26439d4ecbe8b67bb1ae9753454505358ebb6b802624f19800471e53ee27187"
+ "digest": "eab6fbc1824d6e3cd152e8ec1d82e1beaebe02b53b35c6f7a883b8548af02f3a"
},
{
"name": "ao",
"unicode": "1F1E6-1F1F4",
- "digest": "d26439d4ecbe8b67bb1ae9753454505358ebb6b802624f19800471e53ee27187"
+ "digest": "eab6fbc1824d6e3cd152e8ec1d82e1beaebe02b53b35c6f7a883b8548af02f3a"
},
{
"name": "flag_aq",
"unicode": "1F1E6-1F1F6",
- "digest": "6b0b4e800d88ab289ae4b6d449bfa115e92543958b477d13ad348468a74e4616"
+ "digest": "367f6677a683a5f0e7248ab3a8f46d06ba146a0fd75004c70bac0e913147cdaa"
},
{
"name": "aq",
"unicode": "1F1E6-1F1F6",
- "digest": "6b0b4e800d88ab289ae4b6d449bfa115e92543958b477d13ad348468a74e4616"
+ "digest": "367f6677a683a5f0e7248ab3a8f46d06ba146a0fd75004c70bac0e913147cdaa"
},
{
"name": "flag_ar",
"unicode": "1F1E6-1F1F7",
- "digest": "ca76db601dd3f5794f1caace8ab5641fe3786b86e4ae030706162f0ce07d27b3"
+ "digest": "f0dc466b3216957f2679d7208c2d7cf288448b0739b9270a7c5fa717577bdf25"
},
{
"name": "ar",
"unicode": "1F1E6-1F1F7",
- "digest": "ca76db601dd3f5794f1caace8ab5641fe3786b86e4ae030706162f0ce07d27b3"
+ "digest": "f0dc466b3216957f2679d7208c2d7cf288448b0739b9270a7c5fa717577bdf25"
},
{
"name": "flag_as",
"unicode": "1F1E6-1F1F8",
- "digest": "170e1dde0e3fd2e0f2149de5cc8845e15580cc0412e81a643d61bd387de16141"
+ "digest": "fcb7a865c7763c63b23485cc27207b99a3a8492e83d5b5ee2df259a9f68f77d6"
},
{
"name": "as",
"unicode": "1F1E6-1F1F8",
- "digest": "170e1dde0e3fd2e0f2149de5cc8845e15580cc0412e81a643d61bd387de16141"
+ "digest": "fcb7a865c7763c63b23485cc27207b99a3a8492e83d5b5ee2df259a9f68f77d6"
},
{
"name": "flag_at",
"unicode": "1F1E6-1F1F9",
- "digest": "0ab3675a16b4988e87c81e87453c160d6616c7be76247f54c471dc63aa8b42ba"
+ "digest": "1d3d58e9abc034f9a093a94716eddf9811d54dfaf27969fd322b3809fac70217"
},
{
"name": "at",
"unicode": "1F1E6-1F1F9",
- "digest": "0ab3675a16b4988e87c81e87453c160d6616c7be76247f54c471dc63aa8b42ba"
+ "digest": "1d3d58e9abc034f9a093a94716eddf9811d54dfaf27969fd322b3809fac70217"
},
{
"name": "flag_au",
"unicode": "1F1E6-1F1FA",
- "digest": "b6f17d3dfd3547c069a0b6cddd4cf44fb8ce1d1d300e24284fb292ac142537e3"
+ "digest": "789563b64c71a5ad49078d335dc166ef614edb56d1e401885d32fb191c198fbd"
},
{
"name": "au",
"unicode": "1F1E6-1F1FA",
- "digest": "b6f17d3dfd3547c069a0b6cddd4cf44fb8ce1d1d300e24284fb292ac142537e3"
+ "digest": "789563b64c71a5ad49078d335dc166ef614edb56d1e401885d32fb191c198fbd"
},
{
"name": "flag_aw",
"unicode": "1F1E6-1F1FC",
- "digest": "7857bc907f04dfb7ccc4401c05034ad8afb6383a022db77973cfcafa4d6c16c8"
+ "digest": "1504dc3fd8457b44fdf75c15e136dc46a13e8342d1f98949728cdc1238843e0c"
},
{
"name": "aw",
"unicode": "1F1E6-1F1FC",
- "digest": "7857bc907f04dfb7ccc4401c05034ad8afb6383a022db77973cfcafa4d6c16c8"
+ "digest": "1504dc3fd8457b44fdf75c15e136dc46a13e8342d1f98949728cdc1238843e0c"
},
{
"name": "flag_ax",
"unicode": "1F1E6-1F1FD",
- "digest": "ab8f1fd4af7c220a54d478cec5a9f7f3beb5fc83439c448f3ac9848af8391ac1"
+ "digest": "e96fa3525f3be25016a4cf8428261735f3ed5fc9fe5b827b461746a3f08877bf"
},
{
"name": "ax",
"unicode": "1F1E6-1F1FD",
- "digest": "ab8f1fd4af7c220a54d478cec5a9f7f3beb5fc83439c448f3ac9848af8391ac1"
+ "digest": "e96fa3525f3be25016a4cf8428261735f3ed5fc9fe5b827b461746a3f08877bf"
},
{
"name": "flag_az",
"unicode": "1F1E6-1F1FF",
- "digest": "187cc7b6d39800c5910a34409db1e6b1d8aac808c72a93e922a419d9b054fd0b"
+ "digest": "12c366ac2c38b91314fb29056e09fa6e7417766cebde3045859cdb127549f4a2"
},
{
"name": "az",
"unicode": "1F1E6-1F1FF",
- "digest": "187cc7b6d39800c5910a34409db1e6b1d8aac808c72a93e922a419d9b054fd0b"
+ "digest": "12c366ac2c38b91314fb29056e09fa6e7417766cebde3045859cdb127549f4a2"
},
{
"name": "flag_ba",
"unicode": "1F1E7-1F1E6",
- "digest": "cd22c744213087384cf79ed314742026787212c9ceb6999ed166534670f7864a"
+ "digest": "0819ea3901510ac20c7f10e67e5f6c818210f17a362c1d12e299c41feb07f828"
},
{
"name": "ba",
"unicode": "1F1E7-1F1E6",
- "digest": "cd22c744213087384cf79ed314742026787212c9ceb6999ed166534670f7864a"
+ "digest": "0819ea3901510ac20c7f10e67e5f6c818210f17a362c1d12e299c41feb07f828"
},
{
"name": "flag_bb",
"unicode": "1F1E7-1F1E7",
- "digest": "44ff0a48ac2d2180374baa58b1b7c64f26d0d151a48811eb08ffa20758104512"
+ "digest": "cf32778a272ed6cbc8e783b59befd9b204009c69c61a425e148d867808b7fab9"
},
{
"name": "bb",
"unicode": "1F1E7-1F1E7",
- "digest": "44ff0a48ac2d2180374baa58b1b7c64f26d0d151a48811eb08ffa20758104512"
+ "digest": "cf32778a272ed6cbc8e783b59befd9b204009c69c61a425e148d867808b7fab9"
},
{
"name": "flag_bd",
"unicode": "1F1E7-1F1E9",
- "digest": "c18793d2b963458607a0bab94c57e62c8278fce870e96fd8dda78067a8fbde18"
+ "digest": "e6ed186644a874588e879513aec92f8107220dcdd14c766dee61f266ce045665"
},
{
"name": "bd",
"unicode": "1F1E7-1F1E9",
- "digest": "c18793d2b963458607a0bab94c57e62c8278fce870e96fd8dda78067a8fbde18"
+ "digest": "e6ed186644a874588e879513aec92f8107220dcdd14c766dee61f266ce045665"
},
{
"name": "flag_be",
"unicode": "1F1E7-1F1EA",
- "digest": "6e6ccfca064a43b93c8acc04a9425f95af204198022ca20b9ee6c491e99ad950"
+ "digest": "4d941011d15d9f6e755d6f7694884758baf17ac0691bf5d63700f8d6dbcdb948"
},
{
"name": "be",
"unicode": "1F1E7-1F1EA",
- "digest": "6e6ccfca064a43b93c8acc04a9425f95af204198022ca20b9ee6c491e99ad950"
+ "digest": "4d941011d15d9f6e755d6f7694884758baf17ac0691bf5d63700f8d6dbcdb948"
},
{
"name": "flag_bf",
"unicode": "1F1E7-1F1EB",
- "digest": "d69c0394a1c7cb6323f54f024b7d740c728f229ca5e1b54ac374d5024f5470a5"
+ "digest": "fcc57dbda9a86f725f558b6c6309484c97e65f1644aae4f9fb5e642681f6c2e0"
},
{
"name": "bf",
"unicode": "1F1E7-1F1EB",
- "digest": "d69c0394a1c7cb6323f54f024b7d740c728f229ca5e1b54ac374d5024f5470a5"
+ "digest": "fcc57dbda9a86f725f558b6c6309484c97e65f1644aae4f9fb5e642681f6c2e0"
},
{
"name": "flag_bg",
"unicode": "1F1E7-1F1EC",
- "digest": "413a270caf4a9155e84bdba6c9512277f5642246f6ba8d701383a5eeb02f7e95"
+ "digest": "816c47ed96c36c90723da150645902ea8ba18b44757fdd776c7b3542cfecfb18"
},
{
"name": "bg",
"unicode": "1F1E7-1F1EC",
- "digest": "413a270caf4a9155e84bdba6c9512277f5642246f6ba8d701383a5eeb02f7e95"
+ "digest": "816c47ed96c36c90723da150645902ea8ba18b44757fdd776c7b3542cfecfb18"
},
{
"name": "flag_bh",
"unicode": "1F1E7-1F1ED",
- "digest": "9243ed65d7f24c824c2a3207335a2d4ad25251258547c16d0b7b7cbb9df6f8de"
+ "digest": "2cd5c21775a6e73f59d08c9ee0cedf4e8241e562eab939573501d47681987737"
},
{
"name": "bh",
"unicode": "1F1E7-1F1ED",
- "digest": "9243ed65d7f24c824c2a3207335a2d4ad25251258547c16d0b7b7cbb9df6f8de"
+ "digest": "2cd5c21775a6e73f59d08c9ee0cedf4e8241e562eab939573501d47681987737"
},
{
"name": "flag_bi",
"unicode": "1F1E7-1F1EE",
- "digest": "63056519030524b2d2dcd47448267d817205dbd6b98075c97f011a8f1d4d1a4b"
+ "digest": "2da82acbec5518360633c1b0b56d55a79b67237f67d92af5e5cd75a2f3bd550e"
},
{
"name": "bi",
"unicode": "1F1E7-1F1EE",
- "digest": "63056519030524b2d2dcd47448267d817205dbd6b98075c97f011a8f1d4d1a4b"
+ "digest": "2da82acbec5518360633c1b0b56d55a79b67237f67d92af5e5cd75a2f3bd550e"
},
{
"name": "flag_bj",
"unicode": "1F1E7-1F1EF",
- "digest": "93b245eed85d22260d27d1a8c77f51fb3439309e09b2aeca6cd504dbea77b509"
+ "digest": "8fe8c34651eb4e28ab395261a5b72b6f37579535ed676d15de131914e19c0436"
},
{
"name": "bj",
"unicode": "1F1E7-1F1EF",
- "digest": "93b245eed85d22260d27d1a8c77f51fb3439309e09b2aeca6cd504dbea77b509"
+ "digest": "8fe8c34651eb4e28ab395261a5b72b6f37579535ed676d15de131914e19c0436"
},
{
"name": "flag_bl",
"unicode": "1F1E7-1F1F1",
- "digest": "5e1e478deaf02bbaa26595e4cefc5f5c9bec6105ce521b7b9ab4fa5e7a452c14"
+ "digest": "d37f2a215ee7ef5b5ab62d2a0c87e90553b17c6ee310f803a71e9fd72db880e7"
},
{
"name": "bl",
"unicode": "1F1E7-1F1F1",
- "digest": "5e1e478deaf02bbaa26595e4cefc5f5c9bec6105ce521b7b9ab4fa5e7a452c14"
+ "digest": "d37f2a215ee7ef5b5ab62d2a0c87e90553b17c6ee310f803a71e9fd72db880e7"
},
{
"name": "flag_black",
"unicode": "1F3F4",
- "digest": "df131e5c28e9f51dea53fe7f33551f91d420f7d686b7a62980f0154c6b5357a6"
+ "digest": "3740bfc9bcb3b46b697b8b7c47ab2c3e95eca9dbcba12f2bf98a01302704f203"
},
{
"name": "waving_black_flag",
"unicode": "1F3F4",
- "digest": "df131e5c28e9f51dea53fe7f33551f91d420f7d686b7a62980f0154c6b5357a6"
+ "digest": "3740bfc9bcb3b46b697b8b7c47ab2c3e95eca9dbcba12f2bf98a01302704f203"
},
{
"name": "flag_bm",
"unicode": "1F1E7-1F1F2",
- "digest": "9dcd9e60faebe7f93eb19157e99f2ad654a8145c61738de96e6ecd11a246764a"
+ "digest": "ccd21655573f3c955d616c5c7b1eac2be1d4772ff611648d6713ba55d9e4aa9b"
},
{
"name": "bm",
"unicode": "1F1E7-1F1F2",
- "digest": "9dcd9e60faebe7f93eb19157e99f2ad654a8145c61738de96e6ecd11a246764a"
+ "digest": "ccd21655573f3c955d616c5c7b1eac2be1d4772ff611648d6713ba55d9e4aa9b"
},
{
"name": "flag_bn",
"unicode": "1F1E7-1F1F3",
- "digest": "078af6ca481a77871ba005e251a46ce63951c27b1b0cd33b9c1d0d31d349bc1a"
+ "digest": "54330c3d7a37392e69098c213fd8c78f3faab4e7e5909c039188110422514228"
},
{
"name": "bn",
"unicode": "1F1E7-1F1F3",
- "digest": "078af6ca481a77871ba005e251a46ce63951c27b1b0cd33b9c1d0d31d349bc1a"
+ "digest": "54330c3d7a37392e69098c213fd8c78f3faab4e7e5909c039188110422514228"
},
{
"name": "flag_bo",
"unicode": "1F1E7-1F1F4",
- "digest": "92516d04e922a3bcbabe2e7619194bc972c09ba97576e8155f9829c397a71d8c"
+ "digest": "32aff973b26f4f91ca19dddd7861b564da43cfbee87603d8c004f1111342366c"
},
{
"name": "bo",
"unicode": "1F1E7-1F1F4",
- "digest": "92516d04e922a3bcbabe2e7619194bc972c09ba97576e8155f9829c397a71d8c"
+ "digest": "32aff973b26f4f91ca19dddd7861b564da43cfbee87603d8c004f1111342366c"
},
{
"name": "flag_bq",
"unicode": "1F1E7-1F1F6",
- "digest": "7832df5267a2bb8dddb83aeb11162ce79aeebdb718f2ac0e54adcf3d87936171"
+ "digest": "b1ebc959c43f706ca430d8633d9efaa9c60133871506b5f030b730cfb4c19e6f"
},
{
"name": "bq",
"unicode": "1F1E7-1F1F6",
- "digest": "7832df5267a2bb8dddb83aeb11162ce79aeebdb718f2ac0e54adcf3d87936171"
+ "digest": "b1ebc959c43f706ca430d8633d9efaa9c60133871506b5f030b730cfb4c19e6f"
},
{
"name": "flag_br",
"unicode": "1F1E7-1F1F7",
- "digest": "aabcc1c082124045ed214f7d9778d8e2ed791ebb8433defea91db458658abeec"
+ "digest": "64fb154d71fa34ff4838bc405f3e58a4102cf0cb49ca4b06fc3c7a6bf39671f0"
},
{
"name": "br",
"unicode": "1F1E7-1F1F7",
- "digest": "aabcc1c082124045ed214f7d9778d8e2ed791ebb8433defea91db458658abeec"
+ "digest": "64fb154d71fa34ff4838bc405f3e58a4102cf0cb49ca4b06fc3c7a6bf39671f0"
},
{
"name": "flag_bs",
"unicode": "1F1E7-1F1F8",
- "digest": "f628f39003608e181696634929522884165e27ccef55270293f92eeef991635f"
+ "digest": "c4b07e5f652ab06ece95d3774ce8b1399a935f8a28d440cb13cc8bd0b9728ed5"
},
{
"name": "bs",
"unicode": "1F1E7-1F1F8",
- "digest": "f628f39003608e181696634929522884165e27ccef55270293f92eeef991635f"
+ "digest": "c4b07e5f652ab06ece95d3774ce8b1399a935f8a28d440cb13cc8bd0b9728ed5"
},
{
"name": "flag_bt",
"unicode": "1F1E7-1F1F9",
- "digest": "af24a8ab34815da04c3e5af49a47449e0de93b068957cbda695816d0f830ca12"
+ "digest": "901ddbd999dd89a87c1e1208b1470cb4e604a9bc023d0cbcdee64e1bc54079ba"
},
{
"name": "bt",
"unicode": "1F1E7-1F1F9",
- "digest": "af24a8ab34815da04c3e5af49a47449e0de93b068957cbda695816d0f830ca12"
+ "digest": "901ddbd999dd89a87c1e1208b1470cb4e604a9bc023d0cbcdee64e1bc54079ba"
},
{
"name": "flag_bv",
"unicode": "1F1E7-1F1FB",
- "digest": "ff0037f6eed95d4bb5f2b502902360e1ff41426e2896daf3e0730cef1f8f7e41"
+ "digest": "bbf6daa6174c6fbbbf541c8274f31b6757c3a16007c2687015ea041fd1e2c6b6"
},
{
"name": "bv",
"unicode": "1F1E7-1F1FB",
- "digest": "ff0037f6eed95d4bb5f2b502902360e1ff41426e2896daf3e0730cef1f8f7e41"
+ "digest": "bbf6daa6174c6fbbbf541c8274f31b6757c3a16007c2687015ea041fd1e2c6b6"
},
{
"name": "flag_bw",
"unicode": "1F1E7-1F1FC",
- "digest": "3e3241ecb97946cc3e467b083d113a57dd305595e1512d4da18cc403e8689c1d"
+ "digest": "05aa351bc04dc0fe2669441ab500e000d48b1f0d7ad9e885c7abfb898aa0eb3f"
},
{
"name": "bw",
"unicode": "1F1E7-1F1FC",
- "digest": "3e3241ecb97946cc3e467b083d113a57dd305595e1512d4da18cc403e8689c1d"
+ "digest": "05aa351bc04dc0fe2669441ab500e000d48b1f0d7ad9e885c7abfb898aa0eb3f"
},
{
"name": "flag_by",
"unicode": "1F1E7-1F1FE",
- "digest": "bdd21885c6fac475241884a44149b887297772e17617ee59dd9fe8518d52cf3d"
+ "digest": "6eda3b87336ecf0aae4963986d86b916a055d8268c70520303288f235a93b0d9"
},
{
"name": "by",
"unicode": "1F1E7-1F1FE",
- "digest": "bdd21885c6fac475241884a44149b887297772e17617ee59dd9fe8518d52cf3d"
+ "digest": "6eda3b87336ecf0aae4963986d86b916a055d8268c70520303288f235a93b0d9"
},
{
"name": "flag_bz",
"unicode": "1F1E7-1F1FF",
- "digest": "21c16e1da641af004576000bf1db44b9a1e0fccfddc775e96022721c2f18eeea"
+ "digest": "d76ed945b1408558a30a99b8eed6712de968fc49fba1721b5660b8f48087e45a"
},
{
"name": "bz",
"unicode": "1F1E7-1F1FF",
- "digest": "21c16e1da641af004576000bf1db44b9a1e0fccfddc775e96022721c2f18eeea"
+ "digest": "d76ed945b1408558a30a99b8eed6712de968fc49fba1721b5660b8f48087e45a"
},
{
"name": "flag_ca",
"unicode": "1F1E8-1F1E6",
- "digest": "0d00e459084d58d3ea9c60488a9e51bf45f71b77f1600f190225d5ca6ca6c796"
+ "digest": "2fd036047d89751c05de5577909b58347883bc89c3b7d90bec28ad4770a98ecd"
},
{
"name": "ca",
"unicode": "1F1E8-1F1E6",
- "digest": "0d00e459084d58d3ea9c60488a9e51bf45f71b77f1600f190225d5ca6ca6c796"
+ "digest": "2fd036047d89751c05de5577909b58347883bc89c3b7d90bec28ad4770a98ecd"
},
{
"name": "flag_cc",
"unicode": "1F1E8-1F1E8",
- "digest": "86ab27164603ef0f1f83fe898eda6fbb7bc5709f2518f5577f00817860806a7b"
+ "digest": "837ba181a01c71f05d438d205efaaee99f93b2370c97b13e6132f99860323e36"
},
{
"name": "cc",
"unicode": "1F1E8-1F1E8",
- "digest": "86ab27164603ef0f1f83fe898eda6fbb7bc5709f2518f5577f00817860806a7b"
+ "digest": "837ba181a01c71f05d438d205efaaee99f93b2370c97b13e6132f99860323e36"
},
{
"name": "flag_cd",
"unicode": "1F1E8-1F1E9",
- "digest": "fdc2796530ada4bd0bae37ace4bbe707b321b287dcd64568f8e01d3a9df56066"
+ "digest": "318689274b4b3b58aed7fc1654127499a9da69bff1b83e592e86e69d167ce16f"
},
{
"name": "congo",
"unicode": "1F1E8-1F1E9",
- "digest": "fdc2796530ada4bd0bae37ace4bbe707b321b287dcd64568f8e01d3a9df56066"
+ "digest": "318689274b4b3b58aed7fc1654127499a9da69bff1b83e592e86e69d167ce16f"
},
{
"name": "flag_cf",
"unicode": "1F1E8-1F1EB",
- "digest": "5943bec02bede0931e21e7c34a68f375499f60a34883cc1edf2f21e9834b15ce"
+ "digest": "06d6042849d3b7b217c2b18ba787aae449e8c7d2537e2e5974744ec196062228"
},
{
"name": "cf",
"unicode": "1F1E8-1F1EB",
- "digest": "5943bec02bede0931e21e7c34a68f375499f60a34883cc1edf2f21e9834b15ce"
+ "digest": "06d6042849d3b7b217c2b18ba787aae449e8c7d2537e2e5974744ec196062228"
},
{
"name": "flag_cg",
"unicode": "1F1E8-1F1EC",
- "digest": "54498482e2772371e148e05cfb7c5eb55f6a22cd528662abdea10bad47d157da"
+ "digest": "09f45d2dcb5a24d8349ef86e7405cc29ef3d65a908c0bff3221c3b4546547813"
},
{
"name": "cg",
"unicode": "1F1E8-1F1EC",
- "digest": "54498482e2772371e148e05cfb7c5eb55f6a22cd528662abdea10bad47d157da"
+ "digest": "09f45d2dcb5a24d8349ef86e7405cc29ef3d65a908c0bff3221c3b4546547813"
},
{
"name": "flag_ch",
@@ -3142,2162 +3142,2162 @@
{
"name": "flag_ci",
"unicode": "1F1E8-1F1EE",
- "digest": "3a173a3058a5c0174dc88750852cafec264e901ce82a6c69db122c8c0ea71a3a"
+ "digest": "7d85a0c314b7397c9397a54ce2f3a4dc5f40d0234e586dbd8a541a8666f0f51e"
},
{
"name": "ci",
"unicode": "1F1E8-1F1EE",
- "digest": "3a173a3058a5c0174dc88750852cafec264e901ce82a6c69db122c8c0ea71a3a"
+ "digest": "7d85a0c314b7397c9397a54ce2f3a4dc5f40d0234e586dbd8a541a8666f0f51e"
},
{
"name": "flag_ck",
"unicode": "1F1E8-1F1F0",
- "digest": "42f395ff53c618b72b8a224cd4343d1a32f5ad82ced56bf590170a5ff0d5134c"
+ "digest": "c1aa105fe106ed09ed59a596859a0ce4e65a415c59f63df51961491cb947b136"
},
{
"name": "ck",
"unicode": "1F1E8-1F1F0",
- "digest": "42f395ff53c618b72b8a224cd4343d1a32f5ad82ced56bf590170a5ff0d5134c"
+ "digest": "c1aa105fe106ed09ed59a596859a0ce4e65a415c59f63df51961491cb947b136"
},
{
"name": "flag_cl",
"unicode": "1F1E8-1F1F1",
- "digest": "9d6255feb690596904d800e72d5acdb5cda941c5a741b031ea39a3c7650ac46f"
+ "digest": "0fffdad0d892f5c08aaa332af1ed2c228583d89a43190e979a3c3cb020d5a723"
},
{
"name": "chile",
"unicode": "1F1E8-1F1F1",
- "digest": "9d6255feb690596904d800e72d5acdb5cda941c5a741b031ea39a3c7650ac46f"
+ "digest": "0fffdad0d892f5c08aaa332af1ed2c228583d89a43190e979a3c3cb020d5a723"
},
{
"name": "flag_cm",
"unicode": "1F1E8-1F1F2",
- "digest": "ffc99d14e0a8b46a980331090ed9f36f31a87f1b0f8dd8c09007a31c6127c69e"
+ "digest": "e9f55e41a1fd2735a82ad7a7ac39326a944cb20423ffba3608ac53a46036caad"
},
{
"name": "cm",
"unicode": "1F1E8-1F1F2",
- "digest": "ffc99d14e0a8b46a980331090ed9f36f31a87f1b0f8dd8c09007a31c6127c69e"
+ "digest": "e9f55e41a1fd2735a82ad7a7ac39326a944cb20423ffba3608ac53a46036caad"
},
{
"name": "flag_cn",
"unicode": "1F1E8-1F1F3",
- "digest": "869a98c52bdc33591f87e2aab6cb4f13e98bb19136250ff25805d0312a8b7c8a"
+ "digest": "e2c8fee7e3bd51b13d6083d5bf344abe6b9b642e3cbb099d38b4ce341c99d890"
},
{
"name": "cn",
"unicode": "1F1E8-1F1F3",
- "digest": "869a98c52bdc33591f87e2aab6cb4f13e98bb19136250ff25805d0312a8b7c8a"
+ "digest": "e2c8fee7e3bd51b13d6083d5bf344abe6b9b642e3cbb099d38b4ce341c99d890"
},
{
"name": "flag_co",
"unicode": "1F1E8-1F1F4",
- "digest": "6aa458440eb2500ad307fea40fd8f1171a1506a6e32af144a4fd51545bb56151"
+ "digest": "51c60d0979bf8342eaff7cda9faf4b0dfab38efaf5ddf3717eb8f0e2a595b15f"
},
{
"name": "co",
"unicode": "1F1E8-1F1F4",
- "digest": "6aa458440eb2500ad307fea40fd8f1171a1506a6e32af144a4fd51545bb56151"
+ "digest": "51c60d0979bf8342eaff7cda9faf4b0dfab38efaf5ddf3717eb8f0e2a595b15f"
},
{
"name": "flag_cp",
"unicode": "1F1E8-1F1F5",
- "digest": "62627702e3e3768808c12f153a527ffcc492ad74d8cdc1858cfde971efd0c8ee"
+ "digest": "a0124683aa88cd7da886da70c65796c5ad84eb3751e356e9b2aa8ac249cf0bf9"
},
{
"name": "cp",
"unicode": "1F1E8-1F1F5",
- "digest": "62627702e3e3768808c12f153a527ffcc492ad74d8cdc1858cfde971efd0c8ee"
+ "digest": "a0124683aa88cd7da886da70c65796c5ad84eb3751e356e9b2aa8ac249cf0bf9"
},
{
"name": "flag_cr",
"unicode": "1F1E8-1F1F7",
- "digest": "0f3b54d8330c5bb136647547dafc598bda755697cfd6b7d872a2443ba7b5cad4"
+ "digest": "907905971b219e617a34eef4839b0bd08d98f3480e2631bce523120dcef95196"
},
{
"name": "cr",
"unicode": "1F1E8-1F1F7",
- "digest": "0f3b54d8330c5bb136647547dafc598bda755697cfd6b7d872a2443ba7b5cad4"
+ "digest": "907905971b219e617a34eef4839b0bd08d98f3480e2631bce523120dcef95196"
},
{
"name": "flag_cu",
"unicode": "1F1E8-1F1FA",
- "digest": "69bc973002475bb3d9b54cb0ba9ec9cb85f144c1cf54689da0ee8f414ebb0d83"
+ "digest": "d88cea729dc9dbbbcadac0409ec561995f061b2280577c01c6c6b37de347f150"
},
{
"name": "cu",
"unicode": "1F1E8-1F1FA",
- "digest": "69bc973002475bb3d9b54cb0ba9ec9cb85f144c1cf54689da0ee8f414ebb0d83"
+ "digest": "d88cea729dc9dbbbcadac0409ec561995f061b2280577c01c6c6b37de347f150"
},
{
"name": "flag_cv",
"unicode": "1F1E8-1F1FB",
- "digest": "af2e135cf3c1b03a5937c068a75061b5cd332e95902fd0f8dffb2ac2dc89692a"
+ "digest": "5ce97944adfce09e96387e6f872256482ac99ccbc60017c4d58ddd15b6fb67a7"
},
{
"name": "cv",
"unicode": "1F1E8-1F1FB",
- "digest": "af2e135cf3c1b03a5937c068a75061b5cd332e95902fd0f8dffb2ac2dc89692a"
+ "digest": "5ce97944adfce09e96387e6f872256482ac99ccbc60017c4d58ddd15b6fb67a7"
},
{
"name": "flag_cw",
"unicode": "1F1E8-1F1FC",
- "digest": "df4b2228a82f766c5c64c13c1388482a68549e59dd843671ee0eb43506e33411"
+ "digest": "a6fc31bd66ddc2ee8e7bde3aeabfe1c4ad00c9688abae234a541cc1236d68c1b"
},
{
"name": "cw",
"unicode": "1F1E8-1F1FC",
- "digest": "df4b2228a82f766c5c64c13c1388482a68549e59dd843671ee0eb43506e33411"
+ "digest": "a6fc31bd66ddc2ee8e7bde3aeabfe1c4ad00c9688abae234a541cc1236d68c1b"
},
{
"name": "flag_cx",
"unicode": "1F1E8-1F1FD",
- "digest": "db12e513345a7be53954167d359ede0b3effbfb292508ee4d726123e3a8f83d7"
+ "digest": "1261b32bfa22fa1441f5390ff499ac6b921d7ac59cc8acda3deb3a2beb4fb345"
},
{
"name": "cx",
"unicode": "1F1E8-1F1FD",
- "digest": "db12e513345a7be53954167d359ede0b3effbfb292508ee4d726123e3a8f83d7"
+ "digest": "1261b32bfa22fa1441f5390ff499ac6b921d7ac59cc8acda3deb3a2beb4fb345"
},
{
"name": "flag_cy",
"unicode": "1F1E8-1F1FE",
- "digest": "0cea41d4820746e2c6eb408f7ec7419afba9f7396401d92e6c1d77382f721d0b"
+ "digest": "82b1baa05ecffa0ea1f9a83b518163cbd7910985a21955740520bb16b7bb624f"
},
{
"name": "cy",
"unicode": "1F1E8-1F1FE",
- "digest": "0cea41d4820746e2c6eb408f7ec7419afba9f7396401d92e6c1d77382f721d0b"
+ "digest": "82b1baa05ecffa0ea1f9a83b518163cbd7910985a21955740520bb16b7bb624f"
},
{
"name": "flag_cz",
"unicode": "1F1E8-1F1FF",
- "digest": "a1c2405916963be306f761539123486a2845af53716c9dfe94ad5420e14d36c4"
+ "digest": "a169b18968992a52299b67c24fba495e84de28dec2ebb947a08e0d615ac54a5a"
},
{
"name": "cz",
"unicode": "1F1E8-1F1FF",
- "digest": "a1c2405916963be306f761539123486a2845af53716c9dfe94ad5420e14d36c4"
+ "digest": "a169b18968992a52299b67c24fba495e84de28dec2ebb947a08e0d615ac54a5a"
},
{
"name": "flag_de",
"unicode": "1F1E9-1F1EA",
- "digest": "74a80b64437bc4e31bdd7cbb753ecd2d719bf34c506cbac535db83a644174cce"
+ "digest": "99d1906944966a188c72ae592362ed907e2a0bfe95263955c34a0941507b30c1"
},
{
"name": "de",
"unicode": "1F1E9-1F1EA",
- "digest": "74a80b64437bc4e31bdd7cbb753ecd2d719bf34c506cbac535db83a644174cce"
+ "digest": "99d1906944966a188c72ae592362ed907e2a0bfe95263955c34a0941507b30c1"
},
{
"name": "flag_dg",
"unicode": "1F1E9-1F1EC",
- "digest": "13cb5ea872f94a9c3fb579cef417e2d1ed38e8cbe95059576380cacd59bc4b9d"
+ "digest": "dd45e1afe792fca57d4161434bf611bcb7170072d63e4a27fb9dcd6e8912621e"
},
{
"name": "dg",
"unicode": "1F1E9-1F1EC",
- "digest": "13cb5ea872f94a9c3fb579cef417e2d1ed38e8cbe95059576380cacd59bc4b9d"
+ "digest": "dd45e1afe792fca57d4161434bf611bcb7170072d63e4a27fb9dcd6e8912621e"
},
{
"name": "flag_dj",
"unicode": "1F1E9-1F1EF",
- "digest": "5b479654c28d3eeb70055c5e25dc46ccaba9eeea7537cc45ca9dbb8186b743b6"
+ "digest": "e90ba4e98fca71ff0ca5e65c28b911cc52f043428f375d8f954ecbd3b0c8f4dd"
},
{
"name": "dj",
"unicode": "1F1E9-1F1EF",
- "digest": "5b479654c28d3eeb70055c5e25dc46ccaba9eeea7537cc45ca9dbb8186b743b6"
+ "digest": "e90ba4e98fca71ff0ca5e65c28b911cc52f043428f375d8f954ecbd3b0c8f4dd"
},
{
"name": "flag_dk",
"unicode": "1F1E9-1F1F0",
- "digest": "dee7fa9644a9b447417518a353e7edcbb37b2af8bc7d13a6ed71d7210c43ca3c"
+ "digest": "65b3b5f31935a4969d81fedbb8279c7ad32da454d15c5eafcceba5d140927c77"
},
{
"name": "dk",
"unicode": "1F1E9-1F1F0",
- "digest": "dee7fa9644a9b447417518a353e7edcbb37b2af8bc7d13a6ed71d7210c43ca3c"
+ "digest": "65b3b5f31935a4969d81fedbb8279c7ad32da454d15c5eafcceba5d140927c77"
},
{
"name": "flag_dm",
"unicode": "1F1E9-1F1F2",
- "digest": "2e339190a8a0a238140f42e329f6646af5be75763a787ea268488a2e0440dc4c"
+ "digest": "f6225ded6d2cfd6c182ab1a53b8c49dc9df195df11eb7ff27b15f5d3721ba0eb"
},
{
"name": "dm",
"unicode": "1F1E9-1F1F2",
- "digest": "2e339190a8a0a238140f42e329f6646af5be75763a787ea268488a2e0440dc4c"
+ "digest": "f6225ded6d2cfd6c182ab1a53b8c49dc9df195df11eb7ff27b15f5d3721ba0eb"
},
{
"name": "flag_do",
"unicode": "1F1E9-1F1F4",
- "digest": "be5dafcd32d7197a96d37299a91835a8009299452f05a66d91c5fdec17448230"
+ "digest": "dc2ad6856cebbe47c5bd7f5dcf087e4f680d396b2d49440a9b71f0ad49fb8102"
},
{
"name": "do",
"unicode": "1F1E9-1F1F4",
- "digest": "be5dafcd32d7197a96d37299a91835a8009299452f05a66d91c5fdec17448230"
+ "digest": "dc2ad6856cebbe47c5bd7f5dcf087e4f680d396b2d49440a9b71f0ad49fb8102"
},
{
"name": "flag_dz",
"unicode": "1F1E9-1F1FF",
- "digest": "cf525d56bac45fe689f92d441274fc0ecbed4f95591d2c066598f72b1ee8d618"
+ "digest": "ea69fffc4d545f9c0fcef6768257501952955ba4d274c9b81843229a1265c5ed"
},
{
"name": "dz",
"unicode": "1F1E9-1F1FF",
- "digest": "cf525d56bac45fe689f92d441274fc0ecbed4f95591d2c066598f72b1ee8d618"
+ "digest": "ea69fffc4d545f9c0fcef6768257501952955ba4d274c9b81843229a1265c5ed"
},
{
"name": "flag_ea",
"unicode": "1F1EA-1F1E6",
- "digest": "1acb13950f7c3692f9a36e618d8ec10a73ead5d7fa80fb52b6b2a18e3d456002"
+ "digest": "e63bfe15428c481dd23b569e7aaf0a76106e58a946995b4415a81097ecd53b7d"
},
{
"name": "ea",
"unicode": "1F1EA-1F1E6",
- "digest": "1acb13950f7c3692f9a36e618d8ec10a73ead5d7fa80fb52b6b2a18e3d456002"
+ "digest": "e63bfe15428c481dd23b569e7aaf0a76106e58a946995b4415a81097ecd53b7d"
},
{
"name": "flag_ec",
"unicode": "1F1EA-1F1E8",
- "digest": "4d9d35450efc6026651ccc2278e70fb90b001ca5e5eecd31361b1e4e23253dbd"
+ "digest": "0cdabf85cd567047fda1d9a4508220cab829943a7c542c315078db0aac33edac"
},
{
"name": "ec",
"unicode": "1F1EA-1F1E8",
- "digest": "4d9d35450efc6026651ccc2278e70fb90b001ca5e5eecd31361b1e4e23253dbd"
+ "digest": "0cdabf85cd567047fda1d9a4508220cab829943a7c542c315078db0aac33edac"
},
{
"name": "flag_ee",
"unicode": "1F1EA-1F1EA",
- "digest": "86ec7b2f618fe71dddec3d5a621b56b878d683780f1e0ad446f965326d42df48"
+ "digest": "6dc4e3377e8e2af3ff40cf940a914bc7840980b4a14e7da86954343f2b1025fe"
},
{
"name": "ee",
"unicode": "1F1EA-1F1EA",
- "digest": "86ec7b2f618fe71dddec3d5a621b56b878d683780f1e0ad446f965326d42df48"
+ "digest": "6dc4e3377e8e2af3ff40cf940a914bc7840980b4a14e7da86954343f2b1025fe"
},
{
"name": "flag_eg",
"unicode": "1F1EA-1F1EC",
- "digest": "f06d36a6fec15af4c1a76de30e8469847dde2728bb5a48956b4e466098b778a4"
+ "digest": "2ed6bc056015694d75993eb5ee3c1850921d5630681207b04dfbdb982ab346a2"
},
{
"name": "eg",
"unicode": "1F1EA-1F1EC",
- "digest": "f06d36a6fec15af4c1a76de30e8469847dde2728bb5a48956b4e466098b778a4"
+ "digest": "2ed6bc056015694d75993eb5ee3c1850921d5630681207b04dfbdb982ab346a2"
},
{
"name": "flag_eh",
"unicode": "1F1EA-1F1ED",
- "digest": "eb63f5b92c62c98dc008dfa7ad8830aa17fa23964f812a28055bd8b6f5960c5b"
+ "digest": "72adb55943e4df99c00843c65463718609d937480f73dcf4a4451d46b9967a5e"
},
{
"name": "eh",
"unicode": "1F1EA-1F1ED",
- "digest": "eb63f5b92c62c98dc008dfa7ad8830aa17fa23964f812a28055bd8b6f5960c5b"
+ "digest": "72adb55943e4df99c00843c65463718609d937480f73dcf4a4451d46b9967a5e"
},
{
"name": "flag_er",
"unicode": "1F1EA-1F1F7",
- "digest": "e901195f7b37b22a6872d36713de0ec176f6424c209e261e5c849ce318c772f6"
+ "digest": "3fa59331eb5300c8c1f7b1f1bc15cfcfe688da6fa4a79341854598086a44eebc"
},
{
"name": "er",
"unicode": "1F1EA-1F1F7",
- "digest": "e901195f7b37b22a6872d36713de0ec176f6424c209e261e5c849ce318c772f6"
+ "digest": "3fa59331eb5300c8c1f7b1f1bc15cfcfe688da6fa4a79341854598086a44eebc"
},
{
"name": "flag_es",
"unicode": "1F1EA-1F1F8",
- "digest": "27ab5cc6c2e9f26ccdfa632887533eebcd9b514f80cec9e721cf8e5e2544339c"
+ "digest": "1fa1d5cb0a7e8b14aaec758b2e7bf49cdf8f3d09bbcc7dfd589053a432eeae25"
},
{
"name": "es",
"unicode": "1F1EA-1F1F8",
- "digest": "27ab5cc6c2e9f26ccdfa632887533eebcd9b514f80cec9e721cf8e5e2544339c"
+ "digest": "1fa1d5cb0a7e8b14aaec758b2e7bf49cdf8f3d09bbcc7dfd589053a432eeae25"
},
{
"name": "flag_et",
"unicode": "1F1EA-1F1F9",
- "digest": "6cdb3718c9b3ec713258dd36781db58b7da53f3017445056c1a76233e3b4a7de"
+ "digest": "72771decfb214394e4beb594e848ea590c3615800adbba24b5df4c5db6ee9617"
},
{
"name": "et",
"unicode": "1F1EA-1F1F9",
- "digest": "6cdb3718c9b3ec713258dd36781db58b7da53f3017445056c1a76233e3b4a7de"
+ "digest": "72771decfb214394e4beb594e848ea590c3615800adbba24b5df4c5db6ee9617"
},
{
"name": "flag_eu",
"unicode": "1F1EA-1F1FA",
- "digest": "363f60e8a747166d5cec8d70bfdf266411eec2ff07933b6187975075caadfd74"
+ "digest": "4bfa1b2ef23764ead5ef7899806f93e13fd29a09c75e61431579a4116c836aa4"
},
{
"name": "eu",
"unicode": "1F1EA-1F1FA",
- "digest": "363f60e8a747166d5cec8d70bfdf266411eec2ff07933b6187975075caadfd74"
+ "digest": "4bfa1b2ef23764ead5ef7899806f93e13fd29a09c75e61431579a4116c836aa4"
},
{
"name": "flag_fi",
"unicode": "1F1EB-1F1EE",
- "digest": "1a1959cb551a0e8bdaee8c04657fb7387a4d83173f7759f89468da12e1818a9e"
+ "digest": "d0208cdd5b153a2865f9f674179c62871d4675abb0fb639fba88fcd62553f54e"
},
{
"name": "fi",
"unicode": "1F1EB-1F1EE",
- "digest": "1a1959cb551a0e8bdaee8c04657fb7387a4d83173f7759f89468da12e1818a9e"
+ "digest": "d0208cdd5b153a2865f9f674179c62871d4675abb0fb639fba88fcd62553f54e"
},
{
"name": "flag_fj",
"unicode": "1F1EB-1F1EF",
- "digest": "f26dc36ea9c1f32d9bb54874ea384e7118b6e2585be69245fdd73acd8304ae78"
+ "digest": "6c5ec41114af3846b093a418f6e2b5ff7a83cb72cecde75a7dc62e8cb6dcfe45"
},
{
"name": "fj",
"unicode": "1F1EB-1F1EF",
- "digest": "f26dc36ea9c1f32d9bb54874ea384e7118b6e2585be69245fdd73acd8304ae78"
+ "digest": "6c5ec41114af3846b093a418f6e2b5ff7a83cb72cecde75a7dc62e8cb6dcfe45"
},
{
"name": "flag_fk",
"unicode": "1F1EB-1F1F0",
- "digest": "0479e233499b704f91a9b13d083e66296efe2f28ed917ab1496b223bfb09adb8"
+ "digest": "c69ad641d53785deff5c3934b7dcfcd3dc32ffc31b6d3e799d0555b03c23fc15"
},
{
"name": "fk",
"unicode": "1F1EB-1F1F0",
- "digest": "0479e233499b704f91a9b13d083e66296efe2f28ed917ab1496b223bfb09adb8"
+ "digest": "c69ad641d53785deff5c3934b7dcfcd3dc32ffc31b6d3e799d0555b03c23fc15"
},
{
"name": "flag_fm",
"unicode": "1F1EB-1F1F2",
- "digest": "142ea7b4b4a7004329925b495da43ab82351cbaac383c8da6e614b39ba58d05e"
+ "digest": "1e29fb06b273f253c23a9e4aa8ff84bfe22cffb5fa158a0c6f4cdeabe0216990"
},
{
"name": "fm",
"unicode": "1F1EB-1F1F2",
- "digest": "142ea7b4b4a7004329925b495da43ab82351cbaac383c8da6e614b39ba58d05e"
+ "digest": "1e29fb06b273f253c23a9e4aa8ff84bfe22cffb5fa158a0c6f4cdeabe0216990"
},
{
"name": "flag_fo",
"unicode": "1F1EB-1F1F4",
- "digest": "f1c800d4f4d39e2aead9a11ed500f16108d6bc48bd24bd2a1af7b966d8e76752"
+ "digest": "f4907d2f606f4f9d3bef06c6d38e8e88f2a148197b1573668866431a007afc2e"
},
{
"name": "fo",
"unicode": "1F1EB-1F1F4",
- "digest": "f1c800d4f4d39e2aead9a11ed500f16108d6bc48bd24bd2a1af7b966d8e76752"
+ "digest": "f4907d2f606f4f9d3bef06c6d38e8e88f2a148197b1573668866431a007afc2e"
},
{
"name": "flag_fr",
"unicode": "1F1EB-1F1F7",
- "digest": "6f52f36b5199c65ab1cad13ff4e77d2d8b48a8ff79b92166976674ffdc7829ee"
+ "digest": "5a1308ab3cbf6bffcab12588cf3325151a6c72990db7408c2b8605d89f94ed6e"
},
{
"name": "fr",
"unicode": "1F1EB-1F1F7",
- "digest": "6f52f36b5199c65ab1cad13ff4e77d2d8b48a8ff79b92166976674ffdc7829ee"
+ "digest": "5a1308ab3cbf6bffcab12588cf3325151a6c72990db7408c2b8605d89f94ed6e"
},
{
"name": "flag_ga",
"unicode": "1F1EC-1F1E6",
- "digest": "50a0d5a07466e419b74a4d532738f7958de9baa37df6191be4f3755dccc3b326"
+ "digest": "ddc32dee2976507be878ec3d3d2408632ca21bc434cd9f58db4f6ac9774a2db5"
},
{
"name": "ga",
"unicode": "1F1EC-1F1E6",
- "digest": "50a0d5a07466e419b74a4d532738f7958de9baa37df6191be4f3755dccc3b326"
+ "digest": "ddc32dee2976507be878ec3d3d2408632ca21bc434cd9f58db4f6ac9774a2db5"
},
{
"name": "flag_gb",
"unicode": "1F1EC-1F1E7",
- "digest": "220f7da6d5a231b766c79f2e1b7d3fdb74ec0c0c17558cc00a8a8ccdf2afc2e0"
+ "digest": "6b3bb254d134870b02cb066b06e206f652638a915c84b8649ceb30ec67fbebde"
},
{
"name": "gb",
"unicode": "1F1EC-1F1E7",
- "digest": "220f7da6d5a231b766c79f2e1b7d3fdb74ec0c0c17558cc00a8a8ccdf2afc2e0"
+ "digest": "6b3bb254d134870b02cb066b06e206f652638a915c84b8649ceb30ec67fbebde"
},
{
"name": "flag_gd",
"unicode": "1F1EC-1F1E9",
- "digest": "3e162b0d13f4ceea7f663b1d425f13863d104e80df75a640f526e276bcd04081"
+ "digest": "b6a210541ca22d816405f2a7d0d5241dc4d5488c8a36e15bd1e3063f9c41327f"
},
{
"name": "gd",
"unicode": "1F1EC-1F1E9",
- "digest": "3e162b0d13f4ceea7f663b1d425f13863d104e80df75a640f526e276bcd04081"
+ "digest": "b6a210541ca22d816405f2a7d0d5241dc4d5488c8a36e15bd1e3063f9c41327f"
},
{
"name": "flag_ge",
"unicode": "1F1EC-1F1EA",
- "digest": "35897f8254675d2efe9e3070c88af9ef214f08440e6ee75ebe81d28cdb57ea2b"
+ "digest": "e9a5035b7a46b925737e7f7b0ae2419cc4af0e980fbee5bd916edeef13823367"
},
{
"name": "ge",
"unicode": "1F1EC-1F1EA",
- "digest": "35897f8254675d2efe9e3070c88af9ef214f08440e6ee75ebe81d28cdb57ea2b"
+ "digest": "e9a5035b7a46b925737e7f7b0ae2419cc4af0e980fbee5bd916edeef13823367"
},
{
"name": "flag_gf",
"unicode": "1F1EC-1F1EB",
- "digest": "3a34df321635f71a0f2cc4e1eda58d85c29230c77456362345196351bf56533d"
+ "digest": "ce1bcd8c303897c1c22c5994182f21240b4aa635f0d7ce9944f76cbdbf0e4956"
},
{
"name": "gf",
"unicode": "1F1EC-1F1EB",
- "digest": "3a34df321635f71a0f2cc4e1eda58d85c29230c77456362345196351bf56533d"
+ "digest": "ce1bcd8c303897c1c22c5994182f21240b4aa635f0d7ce9944f76cbdbf0e4956"
},
{
"name": "flag_gg",
"unicode": "1F1EC-1F1EC",
- "digest": "c972f8d190b4e9ca8890df41503d202ffd73981833d3f3750f563302167bcd66"
+ "digest": "a435aab3609533ab2d68acd97deba844bfb0fc27b2adac68668223011f23ae5d"
},
{
"name": "gg",
"unicode": "1F1EC-1F1EC",
- "digest": "c972f8d190b4e9ca8890df41503d202ffd73981833d3f3750f563302167bcd66"
+ "digest": "a435aab3609533ab2d68acd97deba844bfb0fc27b2adac68668223011f23ae5d"
},
{
"name": "flag_gh",
"unicode": "1F1EC-1F1ED",
- "digest": "9c3d3569bd411389fa0af7c6938d4325cedeb9c0e8f059dc1d5a74c6b8d6d01b"
+ "digest": "7cad43b40f69b9b00cc1b38036789ce774fd3d597c89f0bf38433847ea69be26"
},
{
"name": "gh",
"unicode": "1F1EC-1F1ED",
- "digest": "9c3d3569bd411389fa0af7c6938d4325cedeb9c0e8f059dc1d5a74c6b8d6d01b"
+ "digest": "7cad43b40f69b9b00cc1b38036789ce774fd3d597c89f0bf38433847ea69be26"
},
{
"name": "flag_gi",
"unicode": "1F1EC-1F1EE",
- "digest": "ede638bc6fedc30a01821025d87ec19297500da9c04a7a155984fca186118649"
+ "digest": "70e9b17d18bf3e0e4d03f4f824323a57909416e4082ca9d8a0796a6959de4f07"
},
{
"name": "gi",
"unicode": "1F1EC-1F1EE",
- "digest": "ede638bc6fedc30a01821025d87ec19297500da9c04a7a155984fca186118649"
+ "digest": "70e9b17d18bf3e0e4d03f4f824323a57909416e4082ca9d8a0796a6959de4f07"
},
{
"name": "flag_gl",
"unicode": "1F1EC-1F1F1",
- "digest": "a2ce3371eff1da8331671925f707232aa593ac7400d59555c9ca689729ce24ec"
+ "digest": "1963d8cca1c1f06b7536b7fb8f5a4782ac0bb05afdf6e481101bce45c58cdd4b"
},
{
"name": "gl",
"unicode": "1F1EC-1F1F1",
- "digest": "a2ce3371eff1da8331671925f707232aa593ac7400d59555c9ca689729ce24ec"
+ "digest": "1963d8cca1c1f06b7536b7fb8f5a4782ac0bb05afdf6e481101bce45c58cdd4b"
},
{
"name": "flag_gm",
"unicode": "1F1EC-1F1F2",
- "digest": "932bf6eb75ddd4278268dd2f09d8fffcfef89f8fd6b6e86a08a414cd3ceec94d"
+ "digest": "6c776a8daa3f4daa2597b0025aec06fc0a53aed262e845d4da3897cd7a89c6a1"
},
{
"name": "gm",
"unicode": "1F1EC-1F1F2",
- "digest": "932bf6eb75ddd4278268dd2f09d8fffcfef89f8fd6b6e86a08a414cd3ceec94d"
+ "digest": "6c776a8daa3f4daa2597b0025aec06fc0a53aed262e845d4da3897cd7a89c6a1"
},
{
"name": "flag_gn",
"unicode": "1F1EC-1F1F3",
- "digest": "ebf543713895adaa09d64897f24bd461191191b8fcbbcede52bdaf4bd2dc67a8"
+ "digest": "134cf7c839370d171ae80a72e5d18d32ea1967df19c191d1a4ea446d649e9558"
},
{
"name": "gn",
"unicode": "1F1EC-1F1F3",
- "digest": "ebf543713895adaa09d64897f24bd461191191b8fcbbcede52bdaf4bd2dc67a8"
+ "digest": "134cf7c839370d171ae80a72e5d18d32ea1967df19c191d1a4ea446d649e9558"
},
{
"name": "flag_gp",
"unicode": "1F1EC-1F1F5",
- "digest": "2e6c48d80c571b34f31fa9b3622dcc51e1707c0118e991e9c177742ff02a8a96"
+ "digest": "be3e906b039ba4884053c78f4f14de9aa87c5573860ccb69ec766068ae3887c2"
},
{
"name": "gp",
"unicode": "1F1EC-1F1F5",
- "digest": "2e6c48d80c571b34f31fa9b3622dcc51e1707c0118e991e9c177742ff02a8a96"
+ "digest": "be3e906b039ba4884053c78f4f14de9aa87c5573860ccb69ec766068ae3887c2"
},
{
"name": "flag_gq",
"unicode": "1F1EC-1F1F6",
- "digest": "b0f5810180d12fc48faf75e73f882dc59072d7bf957f8455bf7e1e336539dc41"
+ "digest": "d476059c4ab41f5a1ef88583087362a5bc57cede930126f37041d1546564ab70"
},
{
"name": "gq",
"unicode": "1F1EC-1F1F6",
- "digest": "b0f5810180d12fc48faf75e73f882dc59072d7bf957f8455bf7e1e336539dc41"
+ "digest": "d476059c4ab41f5a1ef88583087362a5bc57cede930126f37041d1546564ab70"
},
{
"name": "flag_gr",
"unicode": "1F1EC-1F1F7",
- "digest": "8d60d6f8910f5179d851dbea0798b56a492c6be85f3d55e1a1126cd1d6663a3b"
+ "digest": "b9fa9304647aaa08167a07858bb18d778dcc399375f86f580b8d4244794678bc"
},
{
"name": "gr",
"unicode": "1F1EC-1F1F7",
- "digest": "8d60d6f8910f5179d851dbea0798b56a492c6be85f3d55e1a1126cd1d6663a3b"
+ "digest": "b9fa9304647aaa08167a07858bb18d778dcc399375f86f580b8d4244794678bc"
},
{
"name": "flag_gs",
"unicode": "1F1EC-1F1F8",
- "digest": "7b07915af0e2364ebc386a162d44846f3a7986fdd24e20ad2bc56d64a103fe9c"
+ "digest": "de33fbef6e294eb7af36e5b94d8ff573b354a4ff1ebdccf50ca528b86ed601d9"
},
{
"name": "gs",
"unicode": "1F1EC-1F1F8",
- "digest": "7b07915af0e2364ebc386a162d44846f3a7986fdd24e20ad2bc56d64a103fe9c"
+ "digest": "de33fbef6e294eb7af36e5b94d8ff573b354a4ff1ebdccf50ca528b86ed601d9"
},
{
"name": "flag_gt",
"unicode": "1F1EC-1F1F9",
- "digest": "0c78108ede45bf34917b409a0867f5ec8253c74b694beda083f3e8d04d7a10d8"
+ "digest": "4160843e5d642df597c8423eb8e3b74deafe304f3d141c8a4d2fc07509e44832"
},
{
"name": "gt",
"unicode": "1F1EC-1F1F9",
- "digest": "0c78108ede45bf34917b409a0867f5ec8253c74b694beda083f3e8d04d7a10d8"
+ "digest": "4160843e5d642df597c8423eb8e3b74deafe304f3d141c8a4d2fc07509e44832"
},
{
"name": "flag_gu",
"unicode": "1F1EC-1F1FA",
- "digest": "909f1bc98fa1507adb787eb3875503b21ea937d6ae8bb152153916c2da5e13bb"
+ "digest": "3b0cb257ba5b1c3e15d9102410c5f7418da03372e91ce90513de25b9f45283e3"
},
{
"name": "gu",
"unicode": "1F1EC-1F1FA",
- "digest": "909f1bc98fa1507adb787eb3875503b21ea937d6ae8bb152153916c2da5e13bb"
+ "digest": "3b0cb257ba5b1c3e15d9102410c5f7418da03372e91ce90513de25b9f45283e3"
},
{
"name": "flag_gw",
"unicode": "1F1EC-1F1FC",
- "digest": "f5f34410c7b22d5ed9994b47d0e7a9d9a6a1f05c4d3142f7fef3e4409725f5e6"
+ "digest": "bdf07a8f93c0f0a573af5f5361be404a3ba65b729c1a4c05b7632c03d85efc72"
},
{
"name": "gw",
"unicode": "1F1EC-1F1FC",
- "digest": "f5f34410c7b22d5ed9994b47d0e7a9d9a6a1f05c4d3142f7fef3e4409725f5e6"
+ "digest": "bdf07a8f93c0f0a573af5f5361be404a3ba65b729c1a4c05b7632c03d85efc72"
},
{
"name": "flag_gy",
"unicode": "1F1EC-1F1FE",
- "digest": "4939cf52ab34a924a31032b42668960a2c7d8d4f998b16b065c247110df334be"
+ "digest": "b47d8c98b747556f827ad0d1169264eb68ecaf9d2fb76595e8c31866361cbfc6"
},
{
"name": "gy",
"unicode": "1F1EC-1F1FE",
- "digest": "4939cf52ab34a924a31032b42668960a2c7d8d4f998b16b065c247110df334be"
+ "digest": "b47d8c98b747556f827ad0d1169264eb68ecaf9d2fb76595e8c31866361cbfc6"
},
{
"name": "flag_hk",
"unicode": "1F1ED-1F1F0",
- "digest": "bde0916df6d62f6b1cf8f85a8a39526c97fc6ef6fedb0b0cae2adb127a08eafe"
+ "digest": "8e5a54b2e4bd4f5182085299b9648062463da05d535cf0e46a7d9c58eaeb171f"
},
{
"name": "hk",
"unicode": "1F1ED-1F1F0",
- "digest": "bde0916df6d62f6b1cf8f85a8a39526c97fc6ef6fedb0b0cae2adb127a08eafe"
+ "digest": "8e5a54b2e4bd4f5182085299b9648062463da05d535cf0e46a7d9c58eaeb171f"
},
{
"name": "flag_hm",
"unicode": "1F1ED-1F1F2",
- "digest": "603e6c9bff9a0dc941970a313fe98fbf53ff5a57028f1a2766420be4211711cc"
+ "digest": "63c3e080c5e82a72c6d4cf5997ac823dc02184719ec59aadea6dd41b127abf22"
},
{
"name": "hm",
"unicode": "1F1ED-1F1F2",
- "digest": "603e6c9bff9a0dc941970a313fe98fbf53ff5a57028f1a2766420be4211711cc"
+ "digest": "63c3e080c5e82a72c6d4cf5997ac823dc02184719ec59aadea6dd41b127abf22"
},
{
"name": "flag_hn",
"unicode": "1F1ED-1F1F3",
- "digest": "2953ad0909bc32c02615f6ad5a4e5f331ba794a41632b1f0fc366e1c640cc2b9"
+ "digest": "87c1d160db810b5ed208fb33add54f96c17b0f08d87b81f6f09429abf6ec93ac"
},
{
"name": "hn",
"unicode": "1F1ED-1F1F3",
- "digest": "2953ad0909bc32c02615f6ad5a4e5f331ba794a41632b1f0fc366e1c640cc2b9"
+ "digest": "87c1d160db810b5ed208fb33add54f96c17b0f08d87b81f6f09429abf6ec93ac"
},
{
"name": "flag_hr",
"unicode": "1F1ED-1F1F7",
- "digest": "41c9ffc4f0faaa2d77e5cffb781329e7d2489ce879bd8eb9c503621e834abc50"
+ "digest": "8b68112f79baea38565673acf4f1cb90675a5829ff17e4cf9415c928b62aed88"
},
{
"name": "hr",
"unicode": "1F1ED-1F1F7",
- "digest": "41c9ffc4f0faaa2d77e5cffb781329e7d2489ce879bd8eb9c503621e834abc50"
+ "digest": "8b68112f79baea38565673acf4f1cb90675a5829ff17e4cf9415c928b62aed88"
},
{
"name": "flag_ht",
"unicode": "1F1ED-1F1F9",
- "digest": "6a56c3d71b4f858e1774aa2134a9f5584087fec968e9ee8bb1046d2ec93bf059"
+ "digest": "05dbd548c310ef1ebd1724aa85d821f8320106b16ddbf1f6442ea37e4407d5e1"
},
{
"name": "ht",
"unicode": "1F1ED-1F1F9",
- "digest": "6a56c3d71b4f858e1774aa2134a9f5584087fec968e9ee8bb1046d2ec93bf059"
+ "digest": "05dbd548c310ef1ebd1724aa85d821f8320106b16ddbf1f6442ea37e4407d5e1"
},
{
"name": "flag_hu",
"unicode": "1F1ED-1F1FA",
- "digest": "72f5809818d4cab8c0cee73df7f67b820fb8471eea4199911a5917ac099795e8"
+ "digest": "5079f3d6f1459e6df8dda5c19d2367ead8f5a755b8874ac999bae58e3c9f47a7"
},
{
"name": "hu",
"unicode": "1F1ED-1F1FA",
- "digest": "72f5809818d4cab8c0cee73df7f67b820fb8471eea4199911a5917ac099795e8"
+ "digest": "5079f3d6f1459e6df8dda5c19d2367ead8f5a755b8874ac999bae58e3c9f47a7"
},
{
"name": "flag_ic",
"unicode": "1F1EE-1F1E8",
- "digest": "7e2a7667fcd05f927af47e64c5790c104a9956dd9f1a45f03cb0fdcc85d866d3"
+ "digest": "8dcb18c4b75a60867a68d2f6edbf81e782aafb4b9a0404c8081f872dfe71e432"
},
{
"name": "ic",
"unicode": "1F1EE-1F1E8",
- "digest": "7e2a7667fcd05f927af47e64c5790c104a9956dd9f1a45f03cb0fdcc85d866d3"
+ "digest": "8dcb18c4b75a60867a68d2f6edbf81e782aafb4b9a0404c8081f872dfe71e432"
},
{
"name": "flag_id",
"unicode": "1F1EE-1F1E9",
- "digest": "4721f616fae2e443e52f1e9cc96e4835bddca16a2d75d7d5afea57cdee866b7f"
+ "digest": "1b0eb69a158ed3afe24be448d44751f95dcc5cbc7d1393a5753293f16ef0a66c"
},
{
"name": "indonesia",
"unicode": "1F1EE-1F1E9",
- "digest": "4721f616fae2e443e52f1e9cc96e4835bddca16a2d75d7d5afea57cdee866b7f"
+ "digest": "1b0eb69a158ed3afe24be448d44751f95dcc5cbc7d1393a5753293f16ef0a66c"
},
{
"name": "flag_ie",
"unicode": "1F1EE-1F1EA",
- "digest": "84b19833e6c9fb43187f8a28d85045a3df58816f20a07edab90474323174b1f3"
+ "digest": "5fc8c101ad7296224455f72f73c335aa4f676023b68645bafaf69087f69af390"
},
{
"name": "ie",
"unicode": "1F1EE-1F1EA",
- "digest": "84b19833e6c9fb43187f8a28d85045a3df58816f20a07edab90474323174b1f3"
+ "digest": "5fc8c101ad7296224455f72f73c335aa4f676023b68645bafaf69087f69af390"
},
{
"name": "flag_il",
"unicode": "1F1EE-1F1F1",
- "digest": "c99d4bd8c2541cf3a7392c4faf4477d96bc47065dd1423b9e06450483e69b34f"
+ "digest": "5aea4207415b7615dcdd69413705aefda700aefd0d27010cd0a0a338d879d9b8"
},
{
"name": "il",
"unicode": "1F1EE-1F1F1",
- "digest": "c99d4bd8c2541cf3a7392c4faf4477d96bc47065dd1423b9e06450483e69b34f"
+ "digest": "5aea4207415b7615dcdd69413705aefda700aefd0d27010cd0a0a338d879d9b8"
},
{
"name": "flag_im",
"unicode": "1F1EE-1F1F2",
- "digest": "5eeb12c0315b527ce61649a38b64d76af726a73b2d381d1a1ddd1366bafb1bfc"
+ "digest": "1ee9b3a5f1a52fc6d8369bfd81995fc0567e7a61deacd013701b3ec5fd64502e"
},
{
"name": "im",
"unicode": "1F1EE-1F1F2",
- "digest": "5eeb12c0315b527ce61649a38b64d76af726a73b2d381d1a1ddd1366bafb1bfc"
+ "digest": "1ee9b3a5f1a52fc6d8369bfd81995fc0567e7a61deacd013701b3ec5fd64502e"
},
{
"name": "flag_in",
"unicode": "1F1EE-1F1F3",
- "digest": "ecc3cfcff3368fe0875a51a8be9f4dfd449a187e5beb41a2b34241736247f73b"
+ "digest": "202ede502f34d55d180726ac2f29141c6875516f1b3e7ee99f266b16c2fe4bfd"
},
{
"name": "in",
"unicode": "1F1EE-1F1F3",
- "digest": "ecc3cfcff3368fe0875a51a8be9f4dfd449a187e5beb41a2b34241736247f73b"
+ "digest": "202ede502f34d55d180726ac2f29141c6875516f1b3e7ee99f266b16c2fe4bfd"
},
{
"name": "flag_io",
"unicode": "1F1EE-1F1F4",
- "digest": "26243d60e04ba3bc9eb8f008bfc77b2a64bcf1a3d0073eb0449a8c8121618c9c"
+ "digest": "dd45e1afe792fca57d4161434bf611bcb7170072d63e4a27fb9dcd6e8912621e"
},
{
"name": "io",
"unicode": "1F1EE-1F1F4",
- "digest": "26243d60e04ba3bc9eb8f008bfc77b2a64bcf1a3d0073eb0449a8c8121618c9c"
+ "digest": "dd45e1afe792fca57d4161434bf611bcb7170072d63e4a27fb9dcd6e8912621e"
},
{
"name": "flag_iq",
"unicode": "1F1EE-1F1F6",
- "digest": "a1fb5e59575081920b3be5290f654d57a9be099deb56d4ed69eba81a2b531cb3"
+ "digest": "bef294772b5ffccd6c061c19d60af66f61b248d78705faf347ade9ebfca2b46d"
},
{
"name": "iq",
"unicode": "1F1EE-1F1F6",
- "digest": "a1fb5e59575081920b3be5290f654d57a9be099deb56d4ed69eba81a2b531cb3"
+ "digest": "bef294772b5ffccd6c061c19d60af66f61b248d78705faf347ade9ebfca2b46d"
},
{
"name": "flag_ir",
"unicode": "1F1EE-1F1F7",
- "digest": "ab89488b934af1d4bdae7ed16dfc74fffe658bb8e95d5161b48cdd06de44ae85"
+ "digest": "d4faca93577a5546330ab6a09252307e19fb420d89912c0b48ceb90bf409d48e"
},
{
"name": "ir",
"unicode": "1F1EE-1F1F7",
- "digest": "ab89488b934af1d4bdae7ed16dfc74fffe658bb8e95d5161b48cdd06de44ae85"
+ "digest": "d4faca93577a5546330ab6a09252307e19fb420d89912c0b48ceb90bf409d48e"
},
{
"name": "flag_is",
"unicode": "1F1EE-1F1F8",
- "digest": "55db1fc9e6c56d4c9bcb9a46e5e4300cf2a0c32fa91dc24b487a1d56c8097268"
+ "digest": "b2fc04226b274009b4d99d92bcb72b255b534b6fd4b76d82dce1575ad975a456"
},
{
"name": "is",
"unicode": "1F1EE-1F1F8",
- "digest": "55db1fc9e6c56d4c9bcb9a46e5e4300cf2a0c32fa91dc24b487a1d56c8097268"
+ "digest": "b2fc04226b274009b4d99d92bcb72b255b534b6fd4b76d82dce1575ad975a456"
},
{
"name": "flag_it",
"unicode": "1F1EE-1F1F9",
- "digest": "36fc993fb00ab607578a4d0e573e988e17b9459a68a000a48de905a8238589d0"
+ "digest": "735760f193855d55460a0fb93dad55ff67253cab63176eceb90b9bde1faead1e"
},
{
"name": "it",
"unicode": "1F1EE-1F1F9",
- "digest": "36fc993fb00ab607578a4d0e573e988e17b9459a68a000a48de905a8238589d0"
+ "digest": "735760f193855d55460a0fb93dad55ff67253cab63176eceb90b9bde1faead1e"
},
{
"name": "flag_je",
"unicode": "1F1EF-1F1EA",
- "digest": "c608dbfd1259330e2f8c40dc5d12ffd0489396f4fc5f3ca57bcb2f0d9d05c20c"
+ "digest": "671a487a60571d928d2abaf306d0a9ba50239ec54ada14ea29a9a99df658d3cc"
},
{
"name": "je",
"unicode": "1F1EF-1F1EA",
- "digest": "c608dbfd1259330e2f8c40dc5d12ffd0489396f4fc5f3ca57bcb2f0d9d05c20c"
+ "digest": "671a487a60571d928d2abaf306d0a9ba50239ec54ada14ea29a9a99df658d3cc"
},
{
"name": "flag_jm",
"unicode": "1F1EF-1F1F2",
- "digest": "a8224b68b2d324f848d75e4376875ef76a8174e6ba32790d9ca622fe1eabfd5f"
+ "digest": "fb9047199d030b78fc0dcfc58d9b524fdb929238d922809da88147b7cebf4211"
},
{
"name": "jm",
"unicode": "1F1EF-1F1F2",
- "digest": "a8224b68b2d324f848d75e4376875ef76a8174e6ba32790d9ca622fe1eabfd5f"
+ "digest": "fb9047199d030b78fc0dcfc58d9b524fdb929238d922809da88147b7cebf4211"
},
{
"name": "flag_jo",
"unicode": "1F1EF-1F1F4",
- "digest": "2403563dc2ab4ed0e7e3a0761cc09f96801550bba6b177b54d651d8804ad987d"
+ "digest": "19f7d536d0293ebf3db49e05a158097cbde467115ef96523a0553808fd0b4178"
},
{
"name": "jo",
"unicode": "1F1EF-1F1F4",
- "digest": "2403563dc2ab4ed0e7e3a0761cc09f96801550bba6b177b54d651d8804ad987d"
+ "digest": "19f7d536d0293ebf3db49e05a158097cbde467115ef96523a0553808fd0b4178"
},
{
"name": "flag_jp",
"unicode": "1F1EF-1F1F5",
- "digest": "aea8eebd0a0139818cb7629d9c9a8e55160b458eb8ffeee2f36c5cff4b507fd3"
+ "digest": "51e971f777fe481ca9f7e077ecb2ce252c3cc0086b76384e7b965cdc337f3f9e"
},
{
"name": "jp",
"unicode": "1F1EF-1F1F5",
- "digest": "aea8eebd0a0139818cb7629d9c9a8e55160b458eb8ffeee2f36c5cff4b507fd3"
+ "digest": "51e971f777fe481ca9f7e077ecb2ce252c3cc0086b76384e7b965cdc337f3f9e"
},
{
"name": "flag_ke",
"unicode": "1F1F0-1F1EA",
- "digest": "9c8365f74858743bcdce4a9cf6a6f4110faf2dc6433e5dc7d98c24bb3b32a36d"
+ "digest": "0cec8f068548cfd3e7a20c10af84f97ca415fd6f8ab8b50783bf982e77d7260e"
},
{
"name": "ke",
"unicode": "1F1F0-1F1EA",
- "digest": "9c8365f74858743bcdce4a9cf6a6f4110faf2dc6433e5dc7d98c24bb3b32a36d"
+ "digest": "0cec8f068548cfd3e7a20c10af84f97ca415fd6f8ab8b50783bf982e77d7260e"
},
{
"name": "flag_kg",
"unicode": "1F1F0-1F1EC",
- "digest": "0c72bdb1d64b1e3be3d9516a50655a6162d8501851d2cf2fadb8c6ef7740df4e"
+ "digest": "5803ea6ab028261923fd7570c670a50518c6f462a2fb4d463531b12c3e382e6f"
},
{
"name": "kg",
"unicode": "1F1F0-1F1EC",
- "digest": "0c72bdb1d64b1e3be3d9516a50655a6162d8501851d2cf2fadb8c6ef7740df4e"
+ "digest": "5803ea6ab028261923fd7570c670a50518c6f462a2fb4d463531b12c3e382e6f"
},
{
"name": "flag_kh",
"unicode": "1F1F0-1F1ED",
- "digest": "49e41e488732d789e395091e144cd6215c6818ba2073e5e22ea21203a737d03c"
+ "digest": "287d357afe47179853fd485fb102834ead145598ed892664fc62d245cac16080"
},
{
"name": "kh",
"unicode": "1F1F0-1F1ED",
- "digest": "49e41e488732d789e395091e144cd6215c6818ba2073e5e22ea21203a737d03c"
+ "digest": "287d357afe47179853fd485fb102834ead145598ed892664fc62d245cac16080"
},
{
"name": "flag_ki",
"unicode": "1F1F0-1F1EE",
- "digest": "9d7f168adbcf5f4cfe28470addfdb0a8b231438d593edb70f633981bfa4c7638"
+ "digest": "ae4aee0d9cd7a21d4e250d45a484f5f641acdab3d79b437337b25fe34a0b49b0"
},
{
"name": "ki",
"unicode": "1F1F0-1F1EE",
- "digest": "9d7f168adbcf5f4cfe28470addfdb0a8b231438d593edb70f633981bfa4c7638"
+ "digest": "ae4aee0d9cd7a21d4e250d45a484f5f641acdab3d79b437337b25fe34a0b49b0"
},
{
"name": "flag_km",
"unicode": "1F1F0-1F1F2",
- "digest": "9318c28957fa7a19eba5ec452c1cbce01a5a83d41d29d081614d3abb0585d478"
+ "digest": "2d1730acbf5421fd02bd5483e26a86d82ec2fa99f0ff75bfd728a9df7914ad3b"
},
{
"name": "km",
"unicode": "1F1F0-1F1F2",
- "digest": "9318c28957fa7a19eba5ec452c1cbce01a5a83d41d29d081614d3abb0585d478"
+ "digest": "2d1730acbf5421fd02bd5483e26a86d82ec2fa99f0ff75bfd728a9df7914ad3b"
},
{
"name": "flag_kn",
"unicode": "1F1F0-1F1F3",
- "digest": "eac7e7d0f023dee5c0c8559bc2c9a96273adda54ce47598025120b30d8d6ebc1"
+ "digest": "b9ed979db9c6d243b00f61f19a9ec0f2c2390b2e5cace5ad61d9371dc8c670ac"
},
{
"name": "kn",
"unicode": "1F1F0-1F1F3",
- "digest": "eac7e7d0f023dee5c0c8559bc2c9a96273adda54ce47598025120b30d8d6ebc1"
+ "digest": "b9ed979db9c6d243b00f61f19a9ec0f2c2390b2e5cace5ad61d9371dc8c670ac"
},
{
"name": "flag_kp",
"unicode": "1F1F0-1F1F5",
- "digest": "d4d53db6f8363174de6db864c056267ba8a7d7e87b5527f2f42bb9b8ac3f362b"
+ "digest": "1bab0b9cab8028a95ce7231ad8d88ebcd31601cfa321284bba017ead47f6c729"
},
{
"name": "kp",
"unicode": "1F1F0-1F1F5",
- "digest": "d4d53db6f8363174de6db864c056267ba8a7d7e87b5527f2f42bb9b8ac3f362b"
+ "digest": "1bab0b9cab8028a95ce7231ad8d88ebcd31601cfa321284bba017ead47f6c729"
},
{
"name": "flag_kr",
"unicode": "1F1F0-1F1F7",
- "digest": "5c7e61ab4a2aae70cbe51f0ca4718516002bc943b35d870bd853a0c98c4e0ed5"
+ "digest": "33be8c09ebe273e203aa703cc827d52a6d9bf1699f5445bba13a77af2df45fa6"
},
{
"name": "kr",
"unicode": "1F1F0-1F1F7",
- "digest": "5c7e61ab4a2aae70cbe51f0ca4718516002bc943b35d870bd853a0c98c4e0ed5"
+ "digest": "33be8c09ebe273e203aa703cc827d52a6d9bf1699f5445bba13a77af2df45fa6"
},
{
"name": "flag_kw",
"unicode": "1F1F0-1F1FC",
- "digest": "5d229cd99d25f4285bd30d98cfcc3cd8346648897476e2905a1811ceeef48d37"
+ "digest": "04d901a92ea55b13dc4983a9e3adb52dc89c9f3decee86fd06022aa902678b6d"
},
{
"name": "kw",
"unicode": "1F1F0-1F1FC",
- "digest": "5d229cd99d25f4285bd30d98cfcc3cd8346648897476e2905a1811ceeef48d37"
+ "digest": "04d901a92ea55b13dc4983a9e3adb52dc89c9f3decee86fd06022aa902678b6d"
},
{
"name": "flag_ky",
"unicode": "1F1F0-1F1FE",
- "digest": "9ce3d8dfc273d3a400960876c434b702f93df92c6c00682dbed2ec8e3966d8a8"
+ "digest": "10f4d02f33cadd34da89de71a3b763809bad480cd9ae9d2ec000db026bd94cd1"
},
{
"name": "ky",
"unicode": "1F1F0-1F1FE",
- "digest": "9ce3d8dfc273d3a400960876c434b702f93df92c6c00682dbed2ec8e3966d8a8"
+ "digest": "10f4d02f33cadd34da89de71a3b763809bad480cd9ae9d2ec000db026bd94cd1"
},
{
"name": "flag_kz",
"unicode": "1F1F0-1F1FF",
- "digest": "a6f0be0a767fa4824495d568d9fc2bd8d4c1a26f363873d3b65362e9383e2a50"
+ "digest": "dfaff69a78cf635f7fad41bd5bdcc8003298454708a6178ba7348b1b40c360c1"
},
{
"name": "kz",
"unicode": "1F1F0-1F1FF",
- "digest": "a6f0be0a767fa4824495d568d9fc2bd8d4c1a26f363873d3b65362e9383e2a50"
+ "digest": "dfaff69a78cf635f7fad41bd5bdcc8003298454708a6178ba7348b1b40c360c1"
},
{
"name": "flag_la",
"unicode": "1F1F1-1F1E6",
- "digest": "ab2ae96da87f7b53ab212f8dcd897a591cff9ea6666270097a8e739ee0b8f8cb"
+ "digest": "4fcfbdc694cf99ae3f832500cdcdedb88c444b6df88bc9b7141f4f26ba3d5bfd"
},
{
"name": "la",
"unicode": "1F1F1-1F1E6",
- "digest": "ab2ae96da87f7b53ab212f8dcd897a591cff9ea6666270097a8e739ee0b8f8cb"
+ "digest": "4fcfbdc694cf99ae3f832500cdcdedb88c444b6df88bc9b7141f4f26ba3d5bfd"
},
{
"name": "flag_lb",
"unicode": "1F1F1-1F1E7",
- "digest": "0c3fcab22e9fae1c78658290aff97de785d0b6adb5e3702d00073ce774b7ed54"
+ "digest": "af4b1f784bea0ec7a712495491dffbd1152cc857a99fd433f76bfeb313819a62"
},
{
"name": "lb",
"unicode": "1F1F1-1F1E7",
- "digest": "0c3fcab22e9fae1c78658290aff97de785d0b6adb5e3702d00073ce774b7ed54"
+ "digest": "af4b1f784bea0ec7a712495491dffbd1152cc857a99fd433f76bfeb313819a62"
},
{
"name": "flag_lc",
"unicode": "1F1F1-1F1E8",
- "digest": "e154b0b3a1635a36e0d9ad518c0ea12259320e5f1ebbda982248486492065d28"
+ "digest": "40784aa558b75d07ae499c004e2cc5d0b2efdfc3e5be705b5a9f6b70d681c396"
},
{
"name": "lc",
"unicode": "1F1F1-1F1E8",
- "digest": "e154b0b3a1635a36e0d9ad518c0ea12259320e5f1ebbda982248486492065d28"
+ "digest": "40784aa558b75d07ae499c004e2cc5d0b2efdfc3e5be705b5a9f6b70d681c396"
},
{
"name": "flag_li",
"unicode": "1F1F1-1F1EE",
- "digest": "bbc393a89e73cc8c29a0a9297428d07aa1d4717ea9b7d4dd9d69f21ac7d0605d"
+ "digest": "c4eb4c43f457ce60ff9d046adb512c1d3462203403eeb595bff3ebc010ed6633"
},
{
"name": "li",
"unicode": "1F1F1-1F1EE",
- "digest": "bbc393a89e73cc8c29a0a9297428d07aa1d4717ea9b7d4dd9d69f21ac7d0605d"
+ "digest": "c4eb4c43f457ce60ff9d046adb512c1d3462203403eeb595bff3ebc010ed6633"
},
{
"name": "flag_lk",
"unicode": "1F1F1-1F1F0",
- "digest": "376bd501d113a844971ca1006ab31aa086cd55d74842ea5f3dedaba997b58693"
+ "digest": "a5285cdfdc3715fa3941f5f0eb03dc425969eaaf22c719c27ab4418628d09bc5"
},
{
"name": "lk",
"unicode": "1F1F1-1F1F0",
- "digest": "376bd501d113a844971ca1006ab31aa086cd55d74842ea5f3dedaba997b58693"
+ "digest": "a5285cdfdc3715fa3941f5f0eb03dc425969eaaf22c719c27ab4418628d09bc5"
},
{
"name": "flag_lr",
"unicode": "1F1F1-1F1F7",
- "digest": "9a6ebe1c9d9a53079ee77292a5ad0965f96409b0417f92876a1c3bd463d6a9bc"
+ "digest": "ed04334264953b4da570db8c392b99d2fab4e0b7efc2331427016c6a08e818be"
},
{
"name": "lr",
"unicode": "1F1F1-1F1F7",
- "digest": "9a6ebe1c9d9a53079ee77292a5ad0965f96409b0417f92876a1c3bd463d6a9bc"
+ "digest": "ed04334264953b4da570db8c392b99d2fab4e0b7efc2331427016c6a08e818be"
},
{
"name": "flag_ls",
"unicode": "1F1F1-1F1F8",
- "digest": "e2f4b05414f6e0c3d629a92b0534d4145475f0214a83a62c902fe0884c833c89"
+ "digest": "cd56022106d027317cc9bf4c848758cf29ffe277ce71fdb9c1cf89ac4fd6e6db"
},
{
"name": "ls",
"unicode": "1F1F1-1F1F8",
- "digest": "e2f4b05414f6e0c3d629a92b0534d4145475f0214a83a62c902fe0884c833c89"
+ "digest": "cd56022106d027317cc9bf4c848758cf29ffe277ce71fdb9c1cf89ac4fd6e6db"
},
{
"name": "flag_lt",
"unicode": "1F1F1-1F1F9",
- "digest": "d5e2f8b2ffa820a33ea6d612fccd61e32467d25154342f5be134d3520e48387f"
+ "digest": "3c4395b068e421100fd97a102f170cb8d5c093885eef7cb40d3faff4f4e47fe9"
},
{
"name": "lt",
"unicode": "1F1F1-1F1F9",
- "digest": "d5e2f8b2ffa820a33ea6d612fccd61e32467d25154342f5be134d3520e48387f"
+ "digest": "3c4395b068e421100fd97a102f170cb8d5c093885eef7cb40d3faff4f4e47fe9"
},
{
"name": "flag_lu",
"unicode": "1F1F1-1F1FA",
- "digest": "f43277103292195b51981d08e2dde68eab660a65c7875f510e09a8b2370f1b5c"
+ "digest": "df15a2c47eecad17e0cc169bdf0d31c6a51eb22de7ca4e70d2431359a33f930d"
},
{
"name": "lu",
"unicode": "1F1F1-1F1FA",
- "digest": "f43277103292195b51981d08e2dde68eab660a65c7875f510e09a8b2370f1b5c"
+ "digest": "df15a2c47eecad17e0cc169bdf0d31c6a51eb22de7ca4e70d2431359a33f930d"
},
{
"name": "flag_lv",
"unicode": "1F1F1-1F1FB",
- "digest": "e1288ac5c80d6e9d577d652e34be247ca39bf9d3d7cfc8a6cae13c1f9ac9dc47"
+ "digest": "9b53c6ce23287935200da8ca8a8af78013a4b1572f9821e7e1724cbad248e7e2"
},
{
"name": "lv",
"unicode": "1F1F1-1F1FB",
- "digest": "e1288ac5c80d6e9d577d652e34be247ca39bf9d3d7cfc8a6cae13c1f9ac9dc47"
+ "digest": "9b53c6ce23287935200da8ca8a8af78013a4b1572f9821e7e1724cbad248e7e2"
},
{
"name": "flag_ly",
"unicode": "1F1F1-1F1FE",
- "digest": "5122294b769a174e3b6e3d238bb846b3e760929f5bb3c1a708d8a429f3f32f68"
+ "digest": "42efa9f3526ef006d6723fa17538a98ab9556ae25f14df1b06d21361bf7e1a44"
},
{
"name": "ly",
"unicode": "1F1F1-1F1FE",
- "digest": "5122294b769a174e3b6e3d238bb846b3e760929f5bb3c1a708d8a429f3f32f68"
+ "digest": "42efa9f3526ef006d6723fa17538a98ab9556ae25f14df1b06d21361bf7e1a44"
},
{
"name": "flag_ma",
"unicode": "1F1F2-1F1E6",
- "digest": "615a6447ff284de7689b4fd7b04fdda308f65dbbec958cfb96d2977514981d16"
+ "digest": "96c07296cfd7aa1cb642faed8ace26744105b81ca880157a4ef4caee0befe26e"
},
{
"name": "ma",
"unicode": "1F1F2-1F1E6",
- "digest": "615a6447ff284de7689b4fd7b04fdda308f65dbbec958cfb96d2977514981d16"
+ "digest": "96c07296cfd7aa1cb642faed8ace26744105b81ca880157a4ef4caee0befe26e"
},
{
"name": "flag_mc",
"unicode": "1F1F2-1F1E8",
- "digest": "08b48b28938acbfc0fbc15c25ee14dbad7164c5165d03df2eee370755ee7b4cf"
+ "digest": "6b44608842fe849ae2b4bae5eb87ccd436459a427051dfda25080196273d4b9f"
},
{
"name": "mc",
"unicode": "1F1F2-1F1E8",
- "digest": "08b48b28938acbfc0fbc15c25ee14dbad7164c5165d03df2eee370755ee7b4cf"
+ "digest": "6b44608842fe849ae2b4bae5eb87ccd436459a427051dfda25080196273d4b9f"
},
{
"name": "flag_md",
"unicode": "1F1F2-1F1E9",
- "digest": "93d61de68f821e1e08b30e63d91e8b4a657766475128538894cf9da9a3b4e3c0"
+ "digest": "78c7b01c698873a9129d52ba38b3eb4cfc683ef2ae10b7b922b17c07f1c938c8"
},
{
"name": "md",
"unicode": "1F1F2-1F1E9",
- "digest": "93d61de68f821e1e08b30e63d91e8b4a657766475128538894cf9da9a3b4e3c0"
+ "digest": "78c7b01c698873a9129d52ba38b3eb4cfc683ef2ae10b7b922b17c07f1c938c8"
},
{
"name": "flag_me",
"unicode": "1F1F2-1F1EA",
- "digest": "ee55c0eb78241aec2baf1822a47fa46d63209ceae3db7617ae886b823ae229ff"
+ "digest": "01aa0f9df89302edc4ae319b5dd78069ba8807c3f38cc7bfe01bff67c8efd416"
},
{
"name": "me",
"unicode": "1F1F2-1F1EA",
- "digest": "ee55c0eb78241aec2baf1822a47fa46d63209ceae3db7617ae886b823ae229ff"
+ "digest": "01aa0f9df89302edc4ae319b5dd78069ba8807c3f38cc7bfe01bff67c8efd416"
},
{
"name": "flag_mf",
"unicode": "1F1F2-1F1EB",
- "digest": "62627702e3e3768808c12f153a527ffcc492ad74d8cdc1858cfde971efd0c8ee"
+ "digest": "a0124683aa88cd7da886da70c65796c5ad84eb3751e356e9b2aa8ac249cf0bf9"
},
{
"name": "mf",
"unicode": "1F1F2-1F1EB",
- "digest": "62627702e3e3768808c12f153a527ffcc492ad74d8cdc1858cfde971efd0c8ee"
+ "digest": "a0124683aa88cd7da886da70c65796c5ad84eb3751e356e9b2aa8ac249cf0bf9"
},
{
"name": "flag_mg",
"unicode": "1F1F2-1F1EC",
- "digest": "86ec8140e2c4854f52cff74757baf0cbb75a4aacca8be6af8c8f9c939a7b866c"
+ "digest": "56ebcd2a2e144d656d3b38a62595138fe6e50f9c1144f70b0a120cce7a72eb5b"
},
{
"name": "mg",
"unicode": "1F1F2-1F1EC",
- "digest": "86ec8140e2c4854f52cff74757baf0cbb75a4aacca8be6af8c8f9c939a7b866c"
+ "digest": "56ebcd2a2e144d656d3b38a62595138fe6e50f9c1144f70b0a120cce7a72eb5b"
},
{
"name": "flag_mh",
"unicode": "1F1F2-1F1ED",
- "digest": "8311ea3422c9d5e94b55e19b03bedd6fe6e2a191b7657e15ac75a48932958a5b"
+ "digest": "008660adc4c2e4d04830498988184d1ef8a372a6c085da369a94ee6b820dbbb7"
},
{
"name": "mh",
"unicode": "1F1F2-1F1ED",
- "digest": "8311ea3422c9d5e94b55e19b03bedd6fe6e2a191b7657e15ac75a48932958a5b"
+ "digest": "008660adc4c2e4d04830498988184d1ef8a372a6c085da369a94ee6b820dbbb7"
},
{
"name": "flag_mk",
"unicode": "1F1F2-1F1F0",
- "digest": "5c6f504f88c5a875c06ac8b26fa6e81a9d79c42a1c7d1fad9a5d4c8ad06ca502"
+ "digest": "f3c4c5106ace81c21fc0c6a7cc5c5e04e9453468fbc6ccbc851bb8dd61ff237f"
},
{
"name": "mk",
"unicode": "1F1F2-1F1F0",
- "digest": "5c6f504f88c5a875c06ac8b26fa6e81a9d79c42a1c7d1fad9a5d4c8ad06ca502"
+ "digest": "f3c4c5106ace81c21fc0c6a7cc5c5e04e9453468fbc6ccbc851bb8dd61ff237f"
},
{
"name": "flag_ml",
"unicode": "1F1F2-1F1F1",
- "digest": "d08a4973db40cf28e58ca3c80e8bd4e50d68ba1080b31917aeefdb0e210b5c50"
+ "digest": "e70a6b30e46adc2e19684308a848fef2c3ad76e2cac4bb493ee3270ad39f9d1b"
},
{
"name": "ml",
"unicode": "1F1F2-1F1F1",
- "digest": "d08a4973db40cf28e58ca3c80e8bd4e50d68ba1080b31917aeefdb0e210b5c50"
+ "digest": "e70a6b30e46adc2e19684308a848fef2c3ad76e2cac4bb493ee3270ad39f9d1b"
},
{
"name": "flag_mm",
"unicode": "1F1F2-1F1F2",
- "digest": "5e95089514ca09bb93afb481b317477c9d053adcf450e0b711d78ed1078c7470"
+ "digest": "720f5d38887202ba049cd5a46c183679be6a01f169d99e6e656c73b515793a7d"
},
{
"name": "mm",
"unicode": "1F1F2-1F1F2",
- "digest": "5e95089514ca09bb93afb481b317477c9d053adcf450e0b711d78ed1078c7470"
+ "digest": "720f5d38887202ba049cd5a46c183679be6a01f169d99e6e656c73b515793a7d"
},
{
"name": "flag_mn",
"unicode": "1F1F2-1F1F3",
- "digest": "7a0ca72715dd2a36eeeed2f8c888497cb752f0000af8f07d6930743caf6e4273"
+ "digest": "5f0fd6fcb2ed73a5a6d9396c3703612503c1f16283bbb4e9362a1c8324b762ad"
},
{
"name": "mn",
"unicode": "1F1F2-1F1F3",
- "digest": "7a0ca72715dd2a36eeeed2f8c888497cb752f0000af8f07d6930743caf6e4273"
+ "digest": "5f0fd6fcb2ed73a5a6d9396c3703612503c1f16283bbb4e9362a1c8324b762ad"
},
{
"name": "flag_mo",
"unicode": "1F1F2-1F1F4",
- "digest": "d2c7c2191bc1bc83d85f2270968cb4de5cf26a11f70e166a8b32c108287ef729"
+ "digest": "fc2a9e7323867cf195f551e59afdab778c56b84c96af28c20207c9870caa2c39"
},
{
"name": "mo",
"unicode": "1F1F2-1F1F4",
- "digest": "d2c7c2191bc1bc83d85f2270968cb4de5cf26a11f70e166a8b32c108287ef729"
+ "digest": "fc2a9e7323867cf195f551e59afdab778c56b84c96af28c20207c9870caa2c39"
},
{
"name": "flag_mp",
"unicode": "1F1F2-1F1F5",
- "digest": "89ad06121fd7981338fe188464491bea371f85125bfb4fc01fb5cad606613b1e"
+ "digest": "ddce3be9d72914240c42e1b97ea97af01016d0a3879999cb0e447552682c06ba"
},
{
"name": "mp",
"unicode": "1F1F2-1F1F5",
- "digest": "89ad06121fd7981338fe188464491bea371f85125bfb4fc01fb5cad606613b1e"
+ "digest": "ddce3be9d72914240c42e1b97ea97af01016d0a3879999cb0e447552682c06ba"
},
{
"name": "flag_mq",
"unicode": "1F1F2-1F1F6",
- "digest": "98176f3af823b26a3657a17c5073ee22367898b40bd3973de76329aa87ca5a2e"
+ "digest": "888f455b1322d6fb83dc9f469f5505fea3dd6ece77d17d0d7345319c3ebcec0e"
},
{
"name": "mq",
"unicode": "1F1F2-1F1F6",
- "digest": "98176f3af823b26a3657a17c5073ee22367898b40bd3973de76329aa87ca5a2e"
+ "digest": "888f455b1322d6fb83dc9f469f5505fea3dd6ece77d17d0d7345319c3ebcec0e"
},
{
"name": "flag_mr",
"unicode": "1F1F2-1F1F7",
- "digest": "cc3e705ad84f83fe2d544385c39564743024dab26595d62469b35fdb791f6015"
+ "digest": "72621914c92dd9c9f3ac9973ee3589583bfe42b841cdd35f47af75e2f629726c"
},
{
"name": "mr",
"unicode": "1F1F2-1F1F7",
- "digest": "cc3e705ad84f83fe2d544385c39564743024dab26595d62469b35fdb791f6015"
+ "digest": "72621914c92dd9c9f3ac9973ee3589583bfe42b841cdd35f47af75e2f629726c"
},
{
"name": "flag_ms",
"unicode": "1F1F2-1F1F8",
- "digest": "465e3d5700b557f2589bd6e34a0c6b12c634a6ed4dcfbee3c1c841c5de3413f0"
+ "digest": "5944996295132f41ec55261ff7927518bd47aec95d274a6ff257c357b43657bc"
},
{
"name": "ms",
"unicode": "1F1F2-1F1F8",
- "digest": "465e3d5700b557f2589bd6e34a0c6b12c634a6ed4dcfbee3c1c841c5de3413f0"
+ "digest": "5944996295132f41ec55261ff7927518bd47aec95d274a6ff257c357b43657bc"
},
{
"name": "flag_mt",
"unicode": "1F1F2-1F1F9",
- "digest": "e610ba22d8d8ad750ed10dff8e1b4d89bc34f066c3424bfa77dbdc1a5d79743a"
+ "digest": "95f0550e8823441a4e69b26c540baea94f3ddcc282100fd0239021c00df0b469"
},
{
"name": "mt",
"unicode": "1F1F2-1F1F9",
- "digest": "e610ba22d8d8ad750ed10dff8e1b4d89bc34f066c3424bfa77dbdc1a5d79743a"
+ "digest": "95f0550e8823441a4e69b26c540baea94f3ddcc282100fd0239021c00df0b469"
},
{
"name": "flag_mu",
"unicode": "1F1F2-1F1FA",
- "digest": "3daf015d3b95218677dafbb282b7804686aa68875a6bd1d70c165b7b149e19cb"
+ "digest": "5fda78a6df0ea7f5cac5fb4c8fd68529c14c5e15bac4e0b167493cb6ac459253"
},
{
"name": "mu",
"unicode": "1F1F2-1F1FA",
- "digest": "3daf015d3b95218677dafbb282b7804686aa68875a6bd1d70c165b7b149e19cb"
+ "digest": "5fda78a6df0ea7f5cac5fb4c8fd68529c14c5e15bac4e0b167493cb6ac459253"
},
{
"name": "flag_mv",
"unicode": "1F1F2-1F1FB",
- "digest": "d30e4bfd04f08177de92f3c175600aaafa89b9668bbe2b83f35f07a74382065c"
+ "digest": "f75c8f6fd3a68f2944a04c833c649d4b576997f491100cf3f3160fe77117fabb"
},
{
"name": "mv",
"unicode": "1F1F2-1F1FB",
- "digest": "d30e4bfd04f08177de92f3c175600aaafa89b9668bbe2b83f35f07a74382065c"
+ "digest": "f75c8f6fd3a68f2944a04c833c649d4b576997f491100cf3f3160fe77117fabb"
},
{
"name": "flag_mw",
"unicode": "1F1F2-1F1FC",
- "digest": "f364b1c8bfda3f86b5e26422eedc571ba11e312dcc634197631a6840cb22aede"
+ "digest": "d46b484a97e5b90b6b259f8de1712b553f93f0dfb6391209200358bb9429ebf5"
},
{
"name": "mw",
"unicode": "1F1F2-1F1FC",
- "digest": "f364b1c8bfda3f86b5e26422eedc571ba11e312dcc634197631a6840cb22aede"
+ "digest": "d46b484a97e5b90b6b259f8de1712b553f93f0dfb6391209200358bb9429ebf5"
},
{
"name": "flag_mx",
"unicode": "1F1F2-1F1FD",
- "digest": "eafb02ec0be9cefab7cef7c426c7d860d98e4947f4da04054154dc86d8f487c4"
+ "digest": "dc57c10307fc0aa09bd7fcd25ee0fca561f3b382276faa8432a927c1baea53fd"
},
{
"name": "mx",
"unicode": "1F1F2-1F1FD",
- "digest": "eafb02ec0be9cefab7cef7c426c7d860d98e4947f4da04054154dc86d8f487c4"
+ "digest": "dc57c10307fc0aa09bd7fcd25ee0fca561f3b382276faa8432a927c1baea53fd"
},
{
"name": "flag_my",
"unicode": "1F1F2-1F1FE",
- "digest": "9a690b357bc6b970781bd122c1e546ade3ccb73d930c2af1008b82027e36c7cf"
+ "digest": "15ca00660a1eb0096fdaa00b85a7b95fcf192bf2ee4781ba72c36d2d2cb015ef"
},
{
"name": "my",
"unicode": "1F1F2-1F1FE",
- "digest": "9a690b357bc6b970781bd122c1e546ade3ccb73d930c2af1008b82027e36c7cf"
+ "digest": "15ca00660a1eb0096fdaa00b85a7b95fcf192bf2ee4781ba72c36d2d2cb015ef"
},
{
"name": "flag_mz",
"unicode": "1F1F2-1F1FF",
- "digest": "36d0548ebfef9e0443ec1d0597ebfa6e95c25b997381f30c8c74008820743bb9"
+ "digest": "0c8605a9319dcf86672a833b4c4d6acea5f6aa25a3f8e1dfac78fbf7c452ba97"
},
{
"name": "mz",
"unicode": "1F1F2-1F1FF",
- "digest": "36d0548ebfef9e0443ec1d0597ebfa6e95c25b997381f30c8c74008820743bb9"
+ "digest": "0c8605a9319dcf86672a833b4c4d6acea5f6aa25a3f8e1dfac78fbf7c452ba97"
},
{
"name": "flag_na",
"unicode": "1F1F3-1F1E6",
- "digest": "4989dc9452b0bdfa101cfd3b7c83ef1195a7e45128b9ed00193fe712a6d02fca"
+ "digest": "e63cde5ee49d3ada1e33d2ab15dc24fbb129b90d65b6fd1d7c07455f71a53601"
},
{
"name": "na",
"unicode": "1F1F3-1F1E6",
- "digest": "4989dc9452b0bdfa101cfd3b7c83ef1195a7e45128b9ed00193fe712a6d02fca"
+ "digest": "e63cde5ee49d3ada1e33d2ab15dc24fbb129b90d65b6fd1d7c07455f71a53601"
},
{
"name": "flag_nc",
"unicode": "1F1F3-1F1E8",
- "digest": "7fc9d865eebf729d5496c4cd7576476ec599f65b379d4a6df66b4e399553c2eb"
+ "digest": "a4a350ce7404ba7bdda9a341e7a48fcfe16312be4964b1bd6eed7115acd2e329"
},
{
"name": "nc",
"unicode": "1F1F3-1F1E8",
- "digest": "7fc9d865eebf729d5496c4cd7576476ec599f65b379d4a6df66b4e399553c2eb"
+ "digest": "a4a350ce7404ba7bdda9a341e7a48fcfe16312be4964b1bd6eed7115acd2e329"
},
{
"name": "flag_ne",
"unicode": "1F1F3-1F1EA",
- "digest": "d3f10fb44ec44a04112bc66d05f0a44c6ec46dae73cfd3fe26cdc8b32ec06713"
+ "digest": "6b32483b4445bc52855509f618c570b9c9606de5649e4878b71b44ff2acbc9fd"
},
{
"name": "ne",
"unicode": "1F1F3-1F1EA",
- "digest": "d3f10fb44ec44a04112bc66d05f0a44c6ec46dae73cfd3fe26cdc8b32ec06713"
+ "digest": "6b32483b4445bc52855509f618c570b9c9606de5649e4878b71b44ff2acbc9fd"
},
{
"name": "flag_nf",
"unicode": "1F1F3-1F1EB",
- "digest": "d390e0d52215a025380af221ba9e955e5886edbb4c9f4b124f2fb60a8e019e42"
+ "digest": "96b1ec33acbd2b1ffe42703c11a2a633b036e6779849b0e6fa8f399167820584"
},
{
"name": "nf",
"unicode": "1F1F3-1F1EB",
- "digest": "d390e0d52215a025380af221ba9e955e5886edbb4c9f4b124f2fb60a8e019e42"
+ "digest": "96b1ec33acbd2b1ffe42703c11a2a633b036e6779849b0e6fa8f399167820584"
},
{
"name": "flag_ng",
"unicode": "1F1F3-1F1EC",
- "digest": "e69d1bb8f1db4a0c295c90dda23d8f97c2dea59f9a2da2ecb0e9a1dc4dbea101"
+ "digest": "f97d0630cbfa5e75440251df7529a67b58c22598643390cbeea82fb04a1cd956"
},
{
"name": "nigeria",
"unicode": "1F1F3-1F1EC",
- "digest": "e69d1bb8f1db4a0c295c90dda23d8f97c2dea59f9a2da2ecb0e9a1dc4dbea101"
+ "digest": "f97d0630cbfa5e75440251df7529a67b58c22598643390cbeea82fb04a1cd956"
},
{
"name": "flag_ni",
"unicode": "1F1F3-1F1EE",
- "digest": "dbaccc942637469b0ee75bd5f956958c3c5a89d8f69b69c96f02ab6594124894"
+ "digest": "c52fb5f9134122a91defa75425be2c6b3c909e051d546244e0e7bdf5f9ee1710"
},
{
"name": "ni",
"unicode": "1F1F3-1F1EE",
- "digest": "dbaccc942637469b0ee75bd5f956958c3c5a89d8f69b69c96f02ab6594124894"
+ "digest": "c52fb5f9134122a91defa75425be2c6b3c909e051d546244e0e7bdf5f9ee1710"
},
{
"name": "flag_nl",
"unicode": "1F1F3-1F1F1",
- "digest": "bda2eb0315763c3c19d37c664dab1ee4280f20888a0ca57677fd33cfa4240910"
+ "digest": "b8918f9c0c92513aa0ec6ba6cee5448270168cbe6f0a970fb06e7ceb9f52ec71"
},
{
"name": "nl",
"unicode": "1F1F3-1F1F1",
- "digest": "bda2eb0315763c3c19d37c664dab1ee4280f20888a0ca57677fd33cfa4240910"
+ "digest": "b8918f9c0c92513aa0ec6ba6cee5448270168cbe6f0a970fb06e7ceb9f52ec71"
},
{
"name": "flag_no",
"unicode": "1F1F3-1F1F4",
- "digest": "42b49dec756a220781ea271ca8fbcaba524dc3b38d5d8f999bfaa40ef9ebd302"
+ "digest": "05ce84095f8d93407d611b39d8b6a67fd9f11df6cfab7a185bcb4eec186d85ef"
},
{
"name": "no",
"unicode": "1F1F3-1F1F4",
- "digest": "42b49dec756a220781ea271ca8fbcaba524dc3b38d5d8f999bfaa40ef9ebd302"
+ "digest": "05ce84095f8d93407d611b39d8b6a67fd9f11df6cfab7a185bcb4eec186d85ef"
},
{
"name": "flag_np",
"unicode": "1F1F3-1F1F5",
- "digest": "b5259257db079235310d5d9537d2b5b61ae0326bc8920ba13084b009844e2957"
+ "digest": "cc41c2f97ec2b38fe5781d553792f6aab5d37cc3be02586f361fe89d12683bee"
},
{
"name": "np",
"unicode": "1F1F3-1F1F5",
- "digest": "b5259257db079235310d5d9537d2b5b61ae0326bc8920ba13084b009844e2957"
+ "digest": "cc41c2f97ec2b38fe5781d553792f6aab5d37cc3be02586f361fe89d12683bee"
},
{
"name": "flag_nr",
"unicode": "1F1F3-1F1F7",
- "digest": "1bd7d1fe2c3a5e98cfd4dff6e8d6dd6d3c74f0051ad615587d77d2291a9784cc"
+ "digest": "7837edf59ec33a25380d76afea5f04cfcab4f17df4e33fca0dcaacb517c5cbec"
},
{
"name": "nr",
"unicode": "1F1F3-1F1F7",
- "digest": "1bd7d1fe2c3a5e98cfd4dff6e8d6dd6d3c74f0051ad615587d77d2291a9784cc"
+ "digest": "7837edf59ec33a25380d76afea5f04cfcab4f17df4e33fca0dcaacb517c5cbec"
},
{
"name": "flag_nu",
"unicode": "1F1F3-1F1FA",
- "digest": "e2a7a398e07d2232147cc0917d72d18b519246d3d314e9f6f03dcf98d312d4ce"
+ "digest": "fd9ab45c6f32bc4da47542392e5beba73ddac302a4a9a00e6deedc913a4c087d"
},
{
"name": "nu",
"unicode": "1F1F3-1F1FA",
- "digest": "e2a7a398e07d2232147cc0917d72d18b519246d3d314e9f6f03dcf98d312d4ce"
+ "digest": "fd9ab45c6f32bc4da47542392e5beba73ddac302a4a9a00e6deedc913a4c087d"
},
{
"name": "flag_nz",
"unicode": "1F1F3-1F1FF",
- "digest": "ce8b1cb87dae3a3ec865575b57a0b4987a7f4bd3f170e7b210dd764fc2588cd4"
+ "digest": "0719830dcca400cefb30ce399bb03f49dd84c9a98f7d6a28270f9278e2a7af75"
},
{
"name": "nz",
"unicode": "1F1F3-1F1FF",
- "digest": "ce8b1cb87dae3a3ec865575b57a0b4987a7f4bd3f170e7b210dd764fc2588cd4"
+ "digest": "0719830dcca400cefb30ce399bb03f49dd84c9a98f7d6a28270f9278e2a7af75"
},
{
"name": "flag_om",
"unicode": "1F1F4-1F1F2",
- "digest": "29da72505a276a8a372a00c197388ebc5098c221cab26b3ff755bd62b10f740f"
+ "digest": "3f9039becd52e3454fdf7611cdb0d7fb1196e053eea29ef87daab6c21a94f1ee"
},
{
"name": "om",
"unicode": "1F1F4-1F1F2",
- "digest": "29da72505a276a8a372a00c197388ebc5098c221cab26b3ff755bd62b10f740f"
+ "digest": "3f9039becd52e3454fdf7611cdb0d7fb1196e053eea29ef87daab6c21a94f1ee"
},
{
"name": "flag_pa",
"unicode": "1F1F5-1F1E6",
- "digest": "180b673c9aceea43a8b55823a82d80600257e4982d0757d129860e3d8a14f458"
+ "digest": "1adf0e5d4084e072aa44bd9978829e77546e0be75785e9be69f92e326bd714a7"
},
{
"name": "pa",
"unicode": "1F1F5-1F1E6",
- "digest": "180b673c9aceea43a8b55823a82d80600257e4982d0757d129860e3d8a14f458"
+ "digest": "1adf0e5d4084e072aa44bd9978829e77546e0be75785e9be69f92e326bd714a7"
},
{
"name": "flag_pe",
"unicode": "1F1F5-1F1EA",
- "digest": "b61823ea2cd91e371e40832df5764558b81d44fac41030827a3f6d2564643c00"
+ "digest": "f8a4e257676f4ab8962ffe5509b8417777a8be2f0e9dc7735d3e014ff221aab1"
},
{
"name": "pe",
"unicode": "1F1F5-1F1EA",
- "digest": "b61823ea2cd91e371e40832df5764558b81d44fac41030827a3f6d2564643c00"
+ "digest": "f8a4e257676f4ab8962ffe5509b8417777a8be2f0e9dc7735d3e014ff221aab1"
},
{
"name": "flag_pf",
"unicode": "1F1F5-1F1EB",
- "digest": "e560421911f4af90c73a0dbdf8f42e69316003799304c9394fb127e3b83326fa"
+ "digest": "1ace6cc71d130cdf09246297740a911f14828c322e35330cc548ca5975015c23"
},
{
"name": "pf",
"unicode": "1F1F5-1F1EB",
- "digest": "e560421911f4af90c73a0dbdf8f42e69316003799304c9394fb127e3b83326fa"
+ "digest": "1ace6cc71d130cdf09246297740a911f14828c322e35330cc548ca5975015c23"
},
{
"name": "flag_pg",
"unicode": "1F1F5-1F1EC",
- "digest": "880e87db2ce0eac38db037683a5db46fd6ce30623cf56ae4a93a747103570044"
+ "digest": "9c37719d9f51ef31fec0f898d38e522b4253cd00344408e3f660132514efddb7"
},
{
"name": "pg",
"unicode": "1F1F5-1F1EC",
- "digest": "880e87db2ce0eac38db037683a5db46fd6ce30623cf56ae4a93a747103570044"
+ "digest": "9c37719d9f51ef31fec0f898d38e522b4253cd00344408e3f660132514efddb7"
},
{
"name": "flag_ph",
"unicode": "1F1F5-1F1ED",
- "digest": "49aae2f56bfd1385741dc76857aa1f1459778b2d39a1c955e469c5367585bfd5"
+ "digest": "f1af628cf6d1d290cedef3d564b2386e2d6f14ba4426d3fefc0312cb8772e517"
},
{
"name": "ph",
"unicode": "1F1F5-1F1ED",
- "digest": "49aae2f56bfd1385741dc76857aa1f1459778b2d39a1c955e469c5367585bfd5"
+ "digest": "f1af628cf6d1d290cedef3d564b2386e2d6f14ba4426d3fefc0312cb8772e517"
},
{
"name": "flag_pk",
"unicode": "1F1F5-1F1F0",
- "digest": "64379dbfc932df3a07935b5cfa11ca151f761d3728939e982604e12c663cd646"
+ "digest": "61c77f73d2a10a5acb289fadfe0d25d1a1c343e1223bd802099ff4e0e9356521"
},
{
"name": "pk",
"unicode": "1F1F5-1F1F0",
- "digest": "64379dbfc932df3a07935b5cfa11ca151f761d3728939e982604e12c663cd646"
+ "digest": "61c77f73d2a10a5acb289fadfe0d25d1a1c343e1223bd802099ff4e0e9356521"
},
{
"name": "flag_pl",
"unicode": "1F1F5-1F1F1",
- "digest": "3b688b074c2735d3dea0b7ab74b80eba243ce50cb05d68e585c9d701c1f14617"
+ "digest": "38c2c8618446e1f72cf983ab33e736d943f0db7c4cce52a187299e8cec2ea895"
},
{
"name": "pl",
"unicode": "1F1F5-1F1F1",
- "digest": "3b688b074c2735d3dea0b7ab74b80eba243ce50cb05d68e585c9d701c1f14617"
+ "digest": "38c2c8618446e1f72cf983ab33e736d943f0db7c4cce52a187299e8cec2ea895"
},
{
"name": "flag_pm",
"unicode": "1F1F5-1F1F2",
- "digest": "a13a69ee3131501dd8138173cfb669a35ee8039d84aa665e69dd7f0d0aa3e717"
+ "digest": "656be9ea1a79c3885a759c7ce353d338345a198d7939556949affaf5490cb644"
},
{
"name": "pm",
"unicode": "1F1F5-1F1F2",
- "digest": "a13a69ee3131501dd8138173cfb669a35ee8039d84aa665e69dd7f0d0aa3e717"
+ "digest": "656be9ea1a79c3885a759c7ce353d338345a198d7939556949affaf5490cb644"
},
{
"name": "flag_pn",
"unicode": "1F1F5-1F1F3",
- "digest": "d7ae3985cf66024e4a3001e79a8efbb3e75571f2b0abbd0fb87fc1efc795a2b3"
+ "digest": "2792260d8087ab0253b1214c1420f0160ab2eef9afe7315f9e7ff0b87cd15d72"
},
{
"name": "pn",
"unicode": "1F1F5-1F1F3",
- "digest": "d7ae3985cf66024e4a3001e79a8efbb3e75571f2b0abbd0fb87fc1efc795a2b3"
+ "digest": "2792260d8087ab0253b1214c1420f0160ab2eef9afe7315f9e7ff0b87cd15d72"
},
{
"name": "flag_pr",
"unicode": "1F1F5-1F1F7",
- "digest": "4910dc984bc908158506b770f28af56150cbb4509a4291947dfa2479b9e4b308"
+ "digest": "c4cfa1f2201dcda9de310a8247e6ce32d2798ae426a14dd70a9ebb00a2804d46"
},
{
"name": "pr",
"unicode": "1F1F5-1F1F7",
- "digest": "4910dc984bc908158506b770f28af56150cbb4509a4291947dfa2479b9e4b308"
+ "digest": "c4cfa1f2201dcda9de310a8247e6ce32d2798ae426a14dd70a9ebb00a2804d46"
},
{
"name": "flag_ps",
"unicode": "1F1F5-1F1F8",
- "digest": "b2bca7619fced25de94d7bd398537857460348a552e7d73d189aef3f428e6a13"
+ "digest": "197f2ec6294bf0ee4a08cf2f2d1e237ee867c98b3085454a3f42abc955eeb289"
},
{
"name": "ps",
"unicode": "1F1F5-1F1F8",
- "digest": "b2bca7619fced25de94d7bd398537857460348a552e7d73d189aef3f428e6a13"
+ "digest": "197f2ec6294bf0ee4a08cf2f2d1e237ee867c98b3085454a3f42abc955eeb289"
},
{
"name": "flag_pt",
"unicode": "1F1F5-1F1F9",
- "digest": "177282613b4b8b4d9551f1da6a1c3f66f1b96cf67c71c7d164213b26b3237395"
+ "digest": "86a50827963756b5bf471ed9df5b3f2a2058b4c5d778a303414b6b0556e2082b"
},
{
"name": "pt",
"unicode": "1F1F5-1F1F9",
- "digest": "177282613b4b8b4d9551f1da6a1c3f66f1b96cf67c71c7d164213b26b3237395"
+ "digest": "86a50827963756b5bf471ed9df5b3f2a2058b4c5d778a303414b6b0556e2082b"
},
{
"name": "flag_pw",
"unicode": "1F1F5-1F1FC",
- "digest": "2ff42a14bdc7df76b5f989dca381f94765032b26ae47d47b97844abde458cefe"
+ "digest": "a6321c47a0cd188fbfdf3b55f17a7170c63080d28d50e4f5463eb1ee09af2412"
},
{
"name": "pw",
"unicode": "1F1F5-1F1FC",
- "digest": "2ff42a14bdc7df76b5f989dca381f94765032b26ae47d47b97844abde458cefe"
+ "digest": "a6321c47a0cd188fbfdf3b55f17a7170c63080d28d50e4f5463eb1ee09af2412"
},
{
"name": "flag_py",
"unicode": "1F1F5-1F1FE",
- "digest": "80169b69a46c4c67d0090dc2c6bf05d1a14f133ac7ae56f811547e8e8f70d81b"
+ "digest": "1a169e8d8703c510c5a2265b57dbed2f811b03ec375bcb341ab4cd0b100a9dd6"
},
{
"name": "py",
"unicode": "1F1F5-1F1FE",
- "digest": "80169b69a46c4c67d0090dc2c6bf05d1a14f133ac7ae56f811547e8e8f70d81b"
+ "digest": "1a169e8d8703c510c5a2265b57dbed2f811b03ec375bcb341ab4cd0b100a9dd6"
},
{
"name": "flag_qa",
"unicode": "1F1F6-1F1E6",
- "digest": "589b44b975aa97426afb8db7f8b355491fca246b693903485824bf0f5a6953a2"
+ "digest": "de6283965cd98a244b7fa6288174f9ff0d8feb497f191f2e4ab3b690138a3d5d"
},
{
"name": "qa",
"unicode": "1F1F6-1F1E6",
- "digest": "589b44b975aa97426afb8db7f8b355491fca246b693903485824bf0f5a6953a2"
+ "digest": "de6283965cd98a244b7fa6288174f9ff0d8feb497f191f2e4ab3b690138a3d5d"
},
{
"name": "flag_re",
"unicode": "1F1F7-1F1EA",
- "digest": "77d242261742831a142c9ec74cd17d76b1e6d1af751ff3c6a356646744bc798a"
+ "digest": "260e1b97abc1562e5a73d7e53652ffed8059fc9b1c969741c466f48ec6ab0e80"
},
{
"name": "re",
"unicode": "1F1F7-1F1EA",
- "digest": "77d242261742831a142c9ec74cd17d76b1e6d1af751ff3c6a356646744bc798a"
+ "digest": "260e1b97abc1562e5a73d7e53652ffed8059fc9b1c969741c466f48ec6ab0e80"
},
{
"name": "flag_ro",
"unicode": "1F1F7-1F1F4",
- "digest": "d7d17026ea81f27456983722540f9a23343a3a1b22e7697c4fba118ce8b4719e"
+ "digest": "6d648e03955fa2a9fd2bad6f60ec96d3e20ee57f5855f3721a4d4e0c8e99f95c"
},
{
"name": "ro",
"unicode": "1F1F7-1F1F4",
- "digest": "d7d17026ea81f27456983722540f9a23343a3a1b22e7697c4fba118ce8b4719e"
+ "digest": "6d648e03955fa2a9fd2bad6f60ec96d3e20ee57f5855f3721a4d4e0c8e99f95c"
},
{
"name": "flag_rs",
"unicode": "1F1F7-1F1F8",
- "digest": "e466a18cc0368e623d3fe33a036c1e88db91ae24f7510e17caacc85c41f1bac8"
+ "digest": "95cd5e197ed364e403eeb7f1d18a83487d89166910ba8119ea994e5e19d6a7ee"
},
{
"name": "rs",
"unicode": "1F1F7-1F1F8",
- "digest": "e466a18cc0368e623d3fe33a036c1e88db91ae24f7510e17caacc85c41f1bac8"
+ "digest": "95cd5e197ed364e403eeb7f1d18a83487d89166910ba8119ea994e5e19d6a7ee"
},
{
"name": "flag_ru",
"unicode": "1F1F7-1F1FA",
- "digest": "86bf53a62dfc4c434d910f43df70f430fc67c0070fe3fc466c4fbfd6a5d8e646"
+ "digest": "a4a81617a59d9eaf3c526431ca6f90ed334a7c1f516bf70cbd3f1fdc6e6103d7"
},
{
"name": "ru",
"unicode": "1F1F7-1F1FA",
- "digest": "86bf53a62dfc4c434d910f43df70f430fc67c0070fe3fc466c4fbfd6a5d8e646"
+ "digest": "a4a81617a59d9eaf3c526431ca6f90ed334a7c1f516bf70cbd3f1fdc6e6103d7"
},
{
"name": "flag_rw",
"unicode": "1F1F7-1F1FC",
- "digest": "38ec5a01896c9747a8dbf865d5e8584770e587253b7af3d3b9c36cd993f67518"
+ "digest": "7a369f60db0876ffef111c319a3e8c9eaed620c875c51b98ed9ad5207b836dca"
},
{
"name": "rw",
"unicode": "1F1F7-1F1FC",
- "digest": "38ec5a01896c9747a8dbf865d5e8584770e587253b7af3d3b9c36cd993f67518"
+ "digest": "7a369f60db0876ffef111c319a3e8c9eaed620c875c51b98ed9ad5207b836dca"
},
{
"name": "flag_sa",
"unicode": "1F1F8-1F1E6",
- "digest": "a44d0b145f2a0b68eace24ecfd27519e9525ec764836728bc9c1fe96ccb811a0"
+ "digest": "b249fbfd7ed415943f60bbd841965cf721979f960ccbe09396aebac1eca913d7"
},
{
"name": "saudiarabia",
"unicode": "1F1F8-1F1E6",
- "digest": "a44d0b145f2a0b68eace24ecfd27519e9525ec764836728bc9c1fe96ccb811a0"
+ "digest": "b249fbfd7ed415943f60bbd841965cf721979f960ccbe09396aebac1eca913d7"
},
{
"name": "saudi",
"unicode": "1F1F8-1F1E6",
- "digest": "a44d0b145f2a0b68eace24ecfd27519e9525ec764836728bc9c1fe96ccb811a0"
+ "digest": "b249fbfd7ed415943f60bbd841965cf721979f960ccbe09396aebac1eca913d7"
},
{
"name": "flag_sb",
"unicode": "1F1F8-1F1E7",
- "digest": "8ffa24c5cb92be4dbe43f6cd85b61b9608a3101bd78ebccff4fe99c209b3e241"
+ "digest": "526b411260024ea7b6ea6c47f2549345c6cc6960e9a29bfa9aaec0772664d2dc"
},
{
"name": "sb",
"unicode": "1F1F8-1F1E7",
- "digest": "8ffa24c5cb92be4dbe43f6cd85b61b9608a3101bd78ebccff4fe99c209b3e241"
+ "digest": "526b411260024ea7b6ea6c47f2549345c6cc6960e9a29bfa9aaec0772664d2dc"
},
{
"name": "flag_sc",
"unicode": "1F1F8-1F1E8",
- "digest": "227d090ac2cbf317e594567b6114b5063a13cfe33abf990d37b200debcfadabb"
+ "digest": "d036b0d068745926120eaf746fa2e4433306e2e14c6b540d0cd6265e34471056"
},
{
"name": "sc",
"unicode": "1F1F8-1F1E8",
- "digest": "227d090ac2cbf317e594567b6114b5063a13cfe33abf990d37b200debcfadabb"
+ "digest": "d036b0d068745926120eaf746fa2e4433306e2e14c6b540d0cd6265e34471056"
},
{
"name": "flag_sd",
"unicode": "1F1F8-1F1E9",
- "digest": "350f3332e8ea1138e54facc870dd0fea5f2ab7d3fd4baa02ed8627ae79642f6c"
+ "digest": "889615bdb9b1f9c59c5f83ed4d22d54a0ed5dd5de263e729c58544cb06c55885"
},
{
"name": "sd",
"unicode": "1F1F8-1F1E9",
- "digest": "350f3332e8ea1138e54facc870dd0fea5f2ab7d3fd4baa02ed8627ae79642f6c"
+ "digest": "889615bdb9b1f9c59c5f83ed4d22d54a0ed5dd5de263e729c58544cb06c55885"
},
{
"name": "flag_se",
"unicode": "1F1F8-1F1EA",
- "digest": "c1b09f36c263727de83b54376f05e083a17a61941af9a1640b826629256a280d"
+ "digest": "f471d80cfff340960a752c8c152ed4fb482df2a3712b0a56dfab31b9b806926a"
},
{
"name": "se",
"unicode": "1F1F8-1F1EA",
- "digest": "c1b09f36c263727de83b54376f05e083a17a61941af9a1640b826629256a280d"
+ "digest": "f471d80cfff340960a752c8c152ed4fb482df2a3712b0a56dfab31b9b806926a"
},
{
"name": "flag_sg",
"unicode": "1F1F8-1F1EC",
- "digest": "e6fc26920dfc07e4fd3c8d897de9c607e0bf48a3b64a13630c858d707a8e7660"
+ "digest": "82f58a09f98593cc87e545f7e5c03d2aedaf82e54e73f71f58c18e994c3085ac"
},
{
"name": "sg",
"unicode": "1F1F8-1F1EC",
- "digest": "e6fc26920dfc07e4fd3c8d897de9c607e0bf48a3b64a13630c858d707a8e7660"
+ "digest": "82f58a09f98593cc87e545f7e5c03d2aedaf82e54e73f71f58c18e994c3085ac"
},
{
"name": "flag_sh",
"unicode": "1F1F8-1F1ED",
- "digest": "f2c22ab0eb49e3104c35f1c0268b1e63c3a67f41b0cfa9861b189525988e53b6"
+ "digest": "53914b1fa8c1b4f30bae6c1f6717f138fb4dbf482c3e20e33f7aea4ecfc0438d"
},
{
"name": "sh",
"unicode": "1F1F8-1F1ED",
- "digest": "f2c22ab0eb49e3104c35f1c0268b1e63c3a67f41b0cfa9861b189525988e53b6"
+ "digest": "53914b1fa8c1b4f30bae6c1f6717f138fb4dbf482c3e20e33f7aea4ecfc0438d"
},
{
"name": "flag_si",
"unicode": "1F1F8-1F1EE",
- "digest": "1ef0b10e498f71591322f9d8ec122d39838f479370cf7ee922560986ef6c4f2e"
+ "digest": "65d491daa69f9a11cec9ccc4df3a669f12ef95a5c312137776d4472719940ba3"
},
{
"name": "si",
"unicode": "1F1F8-1F1EE",
- "digest": "1ef0b10e498f71591322f9d8ec122d39838f479370cf7ee922560986ef6c4f2e"
+ "digest": "65d491daa69f9a11cec9ccc4df3a669f12ef95a5c312137776d4472719940ba3"
},
{
"name": "flag_sj",
"unicode": "1F1F8-1F1EF",
- "digest": "ce913b007f84a9cba2add8d754aa791901624c60e4200de426dfa25271cb0f78"
+ "digest": "bbf6daa6174c6fbbbf541c8274f31b6757c3a16007c2687015ea041fd1e2c6b6"
},
{
"name": "sj",
"unicode": "1F1F8-1F1EF",
- "digest": "ce913b007f84a9cba2add8d754aa791901624c60e4200de426dfa25271cb0f78"
+ "digest": "bbf6daa6174c6fbbbf541c8274f31b6757c3a16007c2687015ea041fd1e2c6b6"
},
{
"name": "flag_sk",
"unicode": "1F1F8-1F1F0",
- "digest": "d8f8fc4024c82f906effe98facbef9d543fb3708b1134dc502c74dc4a442b30a"
+ "digest": "d4fd03eca5bd3c9fb324ee04fae37c9a2d852bac8335369e3e720ef9b98fff36"
},
{
"name": "sk",
"unicode": "1F1F8-1F1F0",
- "digest": "d8f8fc4024c82f906effe98facbef9d543fb3708b1134dc502c74dc4a442b30a"
+ "digest": "d4fd03eca5bd3c9fb324ee04fae37c9a2d852bac8335369e3e720ef9b98fff36"
},
{
"name": "flag_sl",
"unicode": "1F1F8-1F1F1",
- "digest": "dd7fd0452498d8d1c894cf0d5a662ddff9c5bcc02148bdc3dc7e6f25d0bb586e"
+ "digest": "1455c98c11c248623d82be5484ab1c4dcd1dae449adc393eb1aa2d8c74aa3f02"
},
{
"name": "sl",
"unicode": "1F1F8-1F1F1",
- "digest": "dd7fd0452498d8d1c894cf0d5a662ddff9c5bcc02148bdc3dc7e6f25d0bb586e"
+ "digest": "1455c98c11c248623d82be5484ab1c4dcd1dae449adc393eb1aa2d8c74aa3f02"
},
{
"name": "flag_sm",
"unicode": "1F1F8-1F1F2",
- "digest": "2b499606aee2b5cbf4037338753c80a4c8f75f4abcef2c8657bd9337e602bbd3"
+ "digest": "daec5864ac50c625d7bf49d6c1a170a094cf0d1b9a0bdf62a62406e7ec500a94"
},
{
"name": "sm",
"unicode": "1F1F8-1F1F2",
- "digest": "2b499606aee2b5cbf4037338753c80a4c8f75f4abcef2c8657bd9337e602bbd3"
+ "digest": "daec5864ac50c625d7bf49d6c1a170a094cf0d1b9a0bdf62a62406e7ec500a94"
},
{
"name": "flag_sn",
"unicode": "1F1F8-1F1F3",
- "digest": "03b46a9d8b129da13f60c23b820b04fba52050ca58a41b859ad57d5c3cc2515d"
+ "digest": "4e4d43c467e5eb84c70f535f37f4f468319bd4b06c6ec3db3b54f69efdafd334"
},
{
"name": "sn",
"unicode": "1F1F8-1F1F3",
- "digest": "03b46a9d8b129da13f60c23b820b04fba52050ca58a41b859ad57d5c3cc2515d"
+ "digest": "4e4d43c467e5eb84c70f535f37f4f468319bd4b06c6ec3db3b54f69efdafd334"
},
{
"name": "flag_so",
"unicode": "1F1F8-1F1F4",
- "digest": "ea416b6a05ddc5b16291ebe5101735360b08c834d55ac82c663ac1dd3e459048"
+ "digest": "c1434dca361563a8e3ba88f1ad19c3f6c9cbb8f3ebc17ce128fde2351ff67d0c"
},
{
"name": "so",
"unicode": "1F1F8-1F1F4",
- "digest": "ea416b6a05ddc5b16291ebe5101735360b08c834d55ac82c663ac1dd3e459048"
+ "digest": "c1434dca361563a8e3ba88f1ad19c3f6c9cbb8f3ebc17ce128fde2351ff67d0c"
},
{
"name": "flag_sr",
"unicode": "1F1F8-1F1F7",
- "digest": "012179fbcbcb7343e7b09d33e283fb63c7964a6eca35ccb9407d468e495a9874"
+ "digest": "f3c6bfee2a052f03d56ba917b88595450cef111ffa9e92c7f39ef8c3c3bd12d1"
},
{
"name": "sr",
"unicode": "1F1F8-1F1F7",
- "digest": "012179fbcbcb7343e7b09d33e283fb63c7964a6eca35ccb9407d468e495a9874"
+ "digest": "f3c6bfee2a052f03d56ba917b88595450cef111ffa9e92c7f39ef8c3c3bd12d1"
},
{
"name": "flag_ss",
"unicode": "1F1F8-1F1F8",
- "digest": "6723150482c640643c9dd7e33ea749f4a8b46aceacbd4f5e11aa33b3ee13aab7"
+ "digest": "c0ed7e4f41206f5363e8ebdc6c3f28080e2f07d99e6fb73c1f6226d83310e69d"
},
{
"name": "ss",
"unicode": "1F1F8-1F1F8",
- "digest": "6723150482c640643c9dd7e33ea749f4a8b46aceacbd4f5e11aa33b3ee13aab7"
+ "digest": "c0ed7e4f41206f5363e8ebdc6c3f28080e2f07d99e6fb73c1f6226d83310e69d"
},
{
"name": "flag_st",
"unicode": "1F1F8-1F1F9",
- "digest": "0947fcec2e3cb1b0e9943c3d00891e8ee226e8d0532e9b1fe807ddf2e8fbc49d"
+ "digest": "b022ae5d6885e28c6e9c83c17dd0c24c731d4f3d5773c49051768cdd4df51330"
},
{
"name": "st",
"unicode": "1F1F8-1F1F9",
- "digest": "0947fcec2e3cb1b0e9943c3d00891e8ee226e8d0532e9b1fe807ddf2e8fbc49d"
+ "digest": "b022ae5d6885e28c6e9c83c17dd0c24c731d4f3d5773c49051768cdd4df51330"
},
{
"name": "flag_sv",
"unicode": "1F1F8-1F1FB",
- "digest": "ce7e583db833c4b10e2f7a2d09b97bb522c02e96ea0b3f3a48a955f7d8f970d8"
+ "digest": "5bafdd04d243ee3f3998f4ec0a3d03ff5a3975e771b1f94f89d7713193d7a242"
},
{
"name": "sv",
"unicode": "1F1F8-1F1FB",
- "digest": "ce7e583db833c4b10e2f7a2d09b97bb522c02e96ea0b3f3a48a955f7d8f970d8"
+ "digest": "5bafdd04d243ee3f3998f4ec0a3d03ff5a3975e771b1f94f89d7713193d7a242"
},
{
"name": "flag_sx",
"unicode": "1F1F8-1F1FD",
- "digest": "c01fb238c7ba439f24a5ef821b6457f2a0fd0b99a1b2d02395bed87f0a4a88e5"
+ "digest": "fb92e9f514bcc2f7abbd4e146edde50f030c940c833f184618cbb48e56af22bd"
},
{
"name": "sx",
"unicode": "1F1F8-1F1FD",
- "digest": "c01fb238c7ba439f24a5ef821b6457f2a0fd0b99a1b2d02395bed87f0a4a88e5"
+ "digest": "fb92e9f514bcc2f7abbd4e146edde50f030c940c833f184618cbb48e56af22bd"
},
{
"name": "flag_sy",
"unicode": "1F1F8-1F1FE",
- "digest": "a77d87ef98c96140c59998d10d94837e2a056dd3ac5c7522e89e5c62eac69e69"
+ "digest": "ee330da644d4ce1fdba98be5eaab5054aed8d91a34ab617199a4b2b77f62a10b"
},
{
"name": "sy",
"unicode": "1F1F8-1F1FE",
- "digest": "a77d87ef98c96140c59998d10d94837e2a056dd3ac5c7522e89e5c62eac69e69"
+ "digest": "ee330da644d4ce1fdba98be5eaab5054aed8d91a34ab617199a4b2b77f62a10b"
},
{
"name": "flag_sz",
"unicode": "1F1F8-1F1FF",
- "digest": "2904ad01040a9107ad556ec4c2561781d96746005cca250babb1127b8ba21050"
+ "digest": "7fe0c7429efd9682cc39e57f4bba8d1491d301643ba999d57c4e1bc37517ed64"
},
{
"name": "sz",
"unicode": "1F1F8-1F1FF",
- "digest": "2904ad01040a9107ad556ec4c2561781d96746005cca250babb1127b8ba21050"
+ "digest": "7fe0c7429efd9682cc39e57f4bba8d1491d301643ba999d57c4e1bc37517ed64"
},
{
"name": "flag_ta",
"unicode": "1F1F9-1F1E6",
- "digest": "eda84db90e1a8854e8ff3c15b3b38ee65f7d6532b76970a6fbac304c30d8c959"
+ "digest": "b47e245a2708072a4dbaf190c9606baa4daf02e51627eeae6f20c3b4c95024c0"
},
{
"name": "ta",
"unicode": "1F1F9-1F1E6",
- "digest": "eda84db90e1a8854e8ff3c15b3b38ee65f7d6532b76970a6fbac304c30d8c959"
+ "digest": "b47e245a2708072a4dbaf190c9606baa4daf02e51627eeae6f20c3b4c95024c0"
},
{
"name": "flag_tc",
"unicode": "1F1F9-1F1E8",
- "digest": "4628fdf6dc598a2846beefe97f7d4c6812f4961394cec132924b44bbe79b3322"
+ "digest": "18cfff14c2503b9d24c91c668583d4a14efb17657d800eca86ae49b547c9da5c"
},
{
"name": "tc",
"unicode": "1F1F9-1F1E8",
- "digest": "4628fdf6dc598a2846beefe97f7d4c6812f4961394cec132924b44bbe79b3322"
+ "digest": "18cfff14c2503b9d24c91c668583d4a14efb17657d800eca86ae49b547c9da5c"
},
{
"name": "flag_td",
"unicode": "1F1F9-1F1E9",
- "digest": "125ff31e4285cb2a5493a52a2703ebe8e7138b918ec4dae3d0f8693632372df6"
+ "digest": "73d1db3365736915c4cdf9ba9343d9fd78962203b60334e8f3724d4b330b17db"
},
{
"name": "td",
"unicode": "1F1F9-1F1E9",
- "digest": "125ff31e4285cb2a5493a52a2703ebe8e7138b918ec4dae3d0f8693632372df6"
+ "digest": "73d1db3365736915c4cdf9ba9343d9fd78962203b60334e8f3724d4b330b17db"
},
{
"name": "flag_tf",
"unicode": "1F1F9-1F1EB",
- "digest": "489d591e11764ac341f2234020f7879db782b8f673fc9aae425fd713e4082334"
+ "digest": "3bffeb4bc9ceb9cbb150de88e957b6e46509862ca7d616d5693124af084eb435"
},
{
"name": "tf",
"unicode": "1F1F9-1F1EB",
- "digest": "489d591e11764ac341f2234020f7879db782b8f673fc9aae425fd713e4082334"
+ "digest": "3bffeb4bc9ceb9cbb150de88e957b6e46509862ca7d616d5693124af084eb435"
},
{
"name": "flag_tg",
"unicode": "1F1F9-1F1EC",
- "digest": "4ceedfcfcc22cd14d9add9d86d6748447995f19f7095fa4be883e21eb1aa86bc"
+ "digest": "eb13a0e85baf73326f3ae3bc75e8406eca42000d7e42b0641120e64c0ab7ebaa"
},
{
"name": "tg",
"unicode": "1F1F9-1F1EC",
- "digest": "4ceedfcfcc22cd14d9add9d86d6748447995f19f7095fa4be883e21eb1aa86bc"
+ "digest": "eb13a0e85baf73326f3ae3bc75e8406eca42000d7e42b0641120e64c0ab7ebaa"
},
{
"name": "flag_th",
"unicode": "1F1F9-1F1ED",
- "digest": "2798cc660af1c5dc4891c30aded3a53d7cfa0af128cc495df8141907b165902d"
+ "digest": "a4e42efa4bb94e90f3a92ae9ce14affaacd3a142c1e0da40d8cc839500e771fd"
},
{
"name": "th",
"unicode": "1F1F9-1F1ED",
- "digest": "2798cc660af1c5dc4891c30aded3a53d7cfa0af128cc495df8141907b165902d"
+ "digest": "a4e42efa4bb94e90f3a92ae9ce14affaacd3a142c1e0da40d8cc839500e771fd"
},
{
"name": "flag_tj",
"unicode": "1F1F9-1F1EF",
- "digest": "0483506fc5b5f2d4fc18ea3cd2f8a5da985d68fe4bf90bd3fd05e67e38f32398"
+ "digest": "ff926fa3e86e095683a61c4754355a5b4dd0ecb74393306bd791d130fd1a909d"
},
{
"name": "tj",
"unicode": "1F1F9-1F1EF",
- "digest": "0483506fc5b5f2d4fc18ea3cd2f8a5da985d68fe4bf90bd3fd05e67e38f32398"
+ "digest": "ff926fa3e86e095683a61c4754355a5b4dd0ecb74393306bd791d130fd1a909d"
},
{
"name": "flag_tk",
"unicode": "1F1F9-1F1F0",
- "digest": "d5d4a8c6ce3207731b7c154a9d8d8fa2af055a48f03b3cbbcfd3317d3b8a75f2"
+ "digest": "3fa732d457ded6c83cd5f73d934f64c4e687eb0cde7c157d2fdcdccaf3b5fb52"
},
{
"name": "tk",
"unicode": "1F1F9-1F1F0",
- "digest": "d5d4a8c6ce3207731b7c154a9d8d8fa2af055a48f03b3cbbcfd3317d3b8a75f2"
+ "digest": "3fa732d457ded6c83cd5f73d934f64c4e687eb0cde7c157d2fdcdccaf3b5fb52"
},
{
"name": "flag_tl",
"unicode": "1F1F9-1F1F1",
- "digest": "7a2ba8f91a6b627c60c88244223a9b9d0c12707f50b174f9c2eca07dd3440df7"
+ "digest": "0ec2a4d22fb832060693089e518bbe370a4e13bfc28748f110fc13726409f473"
},
{
"name": "tl",
"unicode": "1F1F9-1F1F1",
- "digest": "7a2ba8f91a6b627c60c88244223a9b9d0c12707f50b174f9c2eca07dd3440df7"
+ "digest": "0ec2a4d22fb832060693089e518bbe370a4e13bfc28748f110fc13726409f473"
},
{
"name": "flag_tm",
"unicode": "1F1F9-1F1F2",
- "digest": "adcf5f23adcf983ce626b44559482f8728251eab34b3ff5d8b125112f3a1010f"
+ "digest": "b4724aa7ad13352f16a0936e61cbb85f0bd147583fc66597aff7e8ee7cf19c21"
},
{
"name": "turkmenistan",
"unicode": "1F1F9-1F1F2",
- "digest": "adcf5f23adcf983ce626b44559482f8728251eab34b3ff5d8b125112f3a1010f"
+ "digest": "b4724aa7ad13352f16a0936e61cbb85f0bd147583fc66597aff7e8ee7cf19c21"
},
{
"name": "flag_tn",
"unicode": "1F1F9-1F1F3",
- "digest": "5ee690ee1f3c3c0cba9b36efdef902894ec59cefbc60c4baa341efd3d7bb9ba2"
+ "digest": "5ab308ffdde40f504d6ee080817bbddbe4f3f4ddb71f508c75e0144a8c8044d9"
},
{
"name": "tn",
"unicode": "1F1F9-1F1F3",
- "digest": "5ee690ee1f3c3c0cba9b36efdef902894ec59cefbc60c4baa341efd3d7bb9ba2"
+ "digest": "5ab308ffdde40f504d6ee080817bbddbe4f3f4ddb71f508c75e0144a8c8044d9"
},
{
"name": "flag_to",
"unicode": "1F1F9-1F1F4",
- "digest": "cde8672ca25b0e3a423865283fab9bc3ab10f472e04979b3b2f8032b71e96300"
+ "digest": "75b7e7198fa42f87986882b8ca251a229afcaa0a1188ae7b9f5ece87dc31a723"
},
{
"name": "to",
"unicode": "1F1F9-1F1F4",
- "digest": "cde8672ca25b0e3a423865283fab9bc3ab10f472e04979b3b2f8032b71e96300"
+ "digest": "75b7e7198fa42f87986882b8ca251a229afcaa0a1188ae7b9f5ece87dc31a723"
},
{
"name": "flag_tr",
"unicode": "1F1F9-1F1F7",
- "digest": "3d83c03ed084cfc81fa633310382acd7213e1eaa19d0ed97d142e7824032b55d"
+ "digest": "9cc48a8f8fa9c17c1627272f68d4740da0e7ce17a2cf8c6b5c08cc9b95e1390c"
},
{
"name": "tr",
"unicode": "1F1F9-1F1F7",
- "digest": "3d83c03ed084cfc81fa633310382acd7213e1eaa19d0ed97d142e7824032b55d"
+ "digest": "9cc48a8f8fa9c17c1627272f68d4740da0e7ce17a2cf8c6b5c08cc9b95e1390c"
},
{
"name": "flag_tt",
"unicode": "1F1F9-1F1F9",
- "digest": "d66d272ac27e2b398289d6b60128ccd3508aeb1f4a00a3920c5e6a21bfe357ed"
+ "digest": "f9e63543121bb3cd2e41bc7b0c2c4ba662bc1cc0520b79fc4e201ec6456fdf59"
},
{
"name": "tt",
"unicode": "1F1F9-1F1F9",
- "digest": "d66d272ac27e2b398289d6b60128ccd3508aeb1f4a00a3920c5e6a21bfe357ed"
+ "digest": "f9e63543121bb3cd2e41bc7b0c2c4ba662bc1cc0520b79fc4e201ec6456fdf59"
},
{
"name": "flag_tv",
"unicode": "1F1F9-1F1FB",
- "digest": "8716527383854cf1569f737d0f0f9ad77b46747255f24e02f5b2fbc850c2e35c"
+ "digest": "6431e5f06cc7995ae7208c429ecf39339b545854cb6d6b7447f465fe53614dfc"
},
{
"name": "tuvalu",
"unicode": "1F1F9-1F1FB",
- "digest": "8716527383854cf1569f737d0f0f9ad77b46747255f24e02f5b2fbc850c2e35c"
+ "digest": "6431e5f06cc7995ae7208c429ecf39339b545854cb6d6b7447f465fe53614dfc"
},
{
"name": "flag_tw",
"unicode": "1F1F9-1F1FC",
- "digest": "fb17b97e18e4423c5f60d60ec3ec60b917be579fc4dd9b5b23236786dcb35108"
+ "digest": "8395ab3c6a595023b006518a5345ac3612f2893d3a8f011b7e5802414236b03c"
},
{
"name": "tw",
"unicode": "1F1F9-1F1FC",
- "digest": "fb17b97e18e4423c5f60d60ec3ec60b917be579fc4dd9b5b23236786dcb35108"
+ "digest": "8395ab3c6a595023b006518a5345ac3612f2893d3a8f011b7e5802414236b03c"
},
{
"name": "flag_tz",
"unicode": "1F1F9-1F1FF",
- "digest": "a8a8cf57ae5227cb54620bf31d2d6e154d2067d6d049b8db64bc4e538222948b"
+ "digest": "716181733cd9ac7a8f51a9a64bc5d21020e8112f6768e8c49c4d651a3ee0b8a4"
},
{
"name": "tz",
"unicode": "1F1F9-1F1FF",
- "digest": "a8a8cf57ae5227cb54620bf31d2d6e154d2067d6d049b8db64bc4e538222948b"
+ "digest": "716181733cd9ac7a8f51a9a64bc5d21020e8112f6768e8c49c4d651a3ee0b8a4"
},
{
"name": "flag_ua",
"unicode": "1F1FA-1F1E6",
- "digest": "03aca4b3ffd60d944a5793eb7530f8d8ae527782f642f6606194e46ee314b12c"
+ "digest": "304570736345e28734f5ff84a2b0481c2bb00bf29d9892bd749b57dec7741e30"
},
{
"name": "ua",
"unicode": "1F1FA-1F1E6",
- "digest": "03aca4b3ffd60d944a5793eb7530f8d8ae527782f642f6606194e46ee314b12c"
+ "digest": "304570736345e28734f5ff84a2b0481c2bb00bf29d9892bd749b57dec7741e30"
},
{
"name": "flag_ug",
"unicode": "1F1FA-1F1EC",
- "digest": "70226a1585e88390b3b815b8b79a0ddb36d2961c6b465c4ff72aa444abfe982e"
+ "digest": "a1bafb74c54ee8c92cb025b55aebdb6081eec3fda6a7f86f2ee14d1b801a8e9c"
},
{
"name": "ug",
"unicode": "1F1FA-1F1EC",
- "digest": "70226a1585e88390b3b815b8b79a0ddb36d2961c6b465c4ff72aa444abfe982e"
+ "digest": "a1bafb74c54ee8c92cb025b55aebdb6081eec3fda6a7f86f2ee14d1b801a8e9c"
},
{
"name": "flag_um",
"unicode": "1F1FA-1F1F2",
- "digest": "aa83bf051149acf907140a860de5de1700710e4164ae5549ad1040b24d0a142b"
+ "digest": "b3c9ac72211f481f50cde09e10b92aa03b1ea90abf85418e60a35b84963273ee"
},
{
"name": "um",
"unicode": "1F1FA-1F1F2",
- "digest": "aa83bf051149acf907140a860de5de1700710e4164ae5549ad1040b24d0a142b"
+ "digest": "b3c9ac72211f481f50cde09e10b92aa03b1ea90abf85418e60a35b84963273ee"
},
{
"name": "flag_us",
"unicode": "1F1FA-1F1F8",
- "digest": "32ba2aa09a30514247e91d60762791b582f547a37d9151f98b700dff50f355ea"
+ "digest": "da79f9af0a188178a82e7dc3a62298fa416f4cfbcae432838df1abebca5c0d63"
},
{
"name": "us",
"unicode": "1F1FA-1F1F8",
- "digest": "32ba2aa09a30514247e91d60762791b582f547a37d9151f98b700dff50f355ea"
+ "digest": "da79f9af0a188178a82e7dc3a62298fa416f4cfbcae432838df1abebca5c0d63"
},
{
"name": "flag_uy",
"unicode": "1F1FA-1F1FE",
- "digest": "0e01b3f1df4bdf6d616dacc9c5825151b941bf074be750e8b24a07ea5d5bcacb"
+ "digest": "8348e901d775722497ee911c9c9b4bd767710760c507630a67ecb6d47cc646c7"
},
{
"name": "uy",
"unicode": "1F1FA-1F1FE",
- "digest": "0e01b3f1df4bdf6d616dacc9c5825151b941bf074be750e8b24a07ea5d5bcacb"
+ "digest": "8348e901d775722497ee911c9c9b4bd767710760c507630a67ecb6d47cc646c7"
},
{
"name": "flag_uz",
"unicode": "1F1FA-1F1FF",
- "digest": "903029ce83812a2134f24b65db35b183443a440ea5fecaa6ef7dcaaf65b2519c"
+ "digest": "2a1dc1e9469e01c58ea91f545ef3fe0bdfe5544a73a80407f8960d01b1e5db5c"
},
{
"name": "uz",
"unicode": "1F1FA-1F1FF",
- "digest": "903029ce83812a2134f24b65db35b183443a440ea5fecaa6ef7dcaaf65b2519c"
+ "digest": "2a1dc1e9469e01c58ea91f545ef3fe0bdfe5544a73a80407f8960d01b1e5db5c"
},
{
"name": "flag_va",
"unicode": "1F1FB-1F1E6",
- "digest": "fd3c1c5d0ac030e838f807288912c98a3e258f87901e252e46942a4dab9f8cb7"
+ "digest": "0e8134ec94bff032bfc63b0b08587d5298c9b7f31edd5a5b35633ae911434e61"
},
{
"name": "va",
"unicode": "1F1FB-1F1E6",
- "digest": "fd3c1c5d0ac030e838f807288912c98a3e258f87901e252e46942a4dab9f8cb7"
+ "digest": "0e8134ec94bff032bfc63b0b08587d5298c9b7f31edd5a5b35633ae911434e61"
},
{
"name": "flag_vc",
"unicode": "1F1FB-1F1E8",
- "digest": "7cd554ea8ca817b5366701160274587ab44167ae5a89c430bbaf237ea18b7421"
+ "digest": "e0290e1be72c8939ee6c398f00a107703b21b97d91b9bf465e553ffbf00304a7"
},
{
"name": "vc",
"unicode": "1F1FB-1F1E8",
- "digest": "7cd554ea8ca817b5366701160274587ab44167ae5a89c430bbaf237ea18b7421"
+ "digest": "e0290e1be72c8939ee6c398f00a107703b21b97d91b9bf465e553ffbf00304a7"
},
{
"name": "flag_ve",
"unicode": "1F1FB-1F1EA",
- "digest": "72930094fb088c1facabea07616035ec4771374358a90c3045219d087b350dd8"
+ "digest": "76a6a6c2353def1f984d1a6980831e63f3aea5af2201b574197834e7c203d57a"
},
{
"name": "ve",
"unicode": "1F1FB-1F1EA",
- "digest": "72930094fb088c1facabea07616035ec4771374358a90c3045219d087b350dd8"
+ "digest": "76a6a6c2353def1f984d1a6980831e63f3aea5af2201b574197834e7c203d57a"
},
{
"name": "flag_vg",
"unicode": "1F1FB-1F1EC",
- "digest": "78a59afd368b7a8312bfdb2f49927ff09e6b8f46aab0136c0453e3319e81df49"
+ "digest": "56fc9317b8dd62cccc60010819f8b895dd4569a9b06368a9250f815c39177b8a"
},
{
"name": "vg",
"unicode": "1F1FB-1F1EC",
- "digest": "78a59afd368b7a8312bfdb2f49927ff09e6b8f46aab0136c0453e3319e81df49"
+ "digest": "56fc9317b8dd62cccc60010819f8b895dd4569a9b06368a9250f815c39177b8a"
},
{
"name": "flag_vi",
"unicode": "1F1FB-1F1EE",
- "digest": "e070879f9605a9bae66bb84f2abf5a40c8b264baee65cd4f7a6720b826739f29"
+ "digest": "2526a3e13b8ccd301f0763580430898c227bd209e3ce482c7951140b28948375"
},
{
"name": "vi",
"unicode": "1F1FB-1F1EE",
- "digest": "e070879f9605a9bae66bb84f2abf5a40c8b264baee65cd4f7a6720b826739f29"
+ "digest": "2526a3e13b8ccd301f0763580430898c227bd209e3ce482c7951140b28948375"
},
{
"name": "flag_vn",
"unicode": "1F1FB-1F1F3",
- "digest": "100ddf06e0f239b170f4d6cb459450bf4945281ee818f7d3c061828b80562219"
+ "digest": "0cf6b9896bbe4da8ed7718d0abfd56cef1a8321e26f89d3ad1b48488eaffb7a5"
},
{
"name": "vn",
"unicode": "1F1FB-1F1F3",
- "digest": "100ddf06e0f239b170f4d6cb459450bf4945281ee818f7d3c061828b80562219"
+ "digest": "0cf6b9896bbe4da8ed7718d0abfd56cef1a8321e26f89d3ad1b48488eaffb7a5"
},
{
"name": "flag_vu",
"unicode": "1F1FB-1F1FA",
- "digest": "59fc9d16818295bba4f7f551598f85378cd07f2bd7e31a4eef2589aaa3847563"
+ "digest": "9dfa282ce1aafc62beacab76e1fc19a141c8bdeaa30898f69b083067b775d362"
},
{
"name": "vu",
"unicode": "1F1FB-1F1FA",
- "digest": "59fc9d16818295bba4f7f551598f85378cd07f2bd7e31a4eef2589aaa3847563"
+ "digest": "9dfa282ce1aafc62beacab76e1fc19a141c8bdeaa30898f69b083067b775d362"
},
{
"name": "flag_wf",
"unicode": "1F1FC-1F1EB",
- "digest": "62627702e3e3768808c12f153a527ffcc492ad74d8cdc1858cfde971efd0c8ee"
+ "digest": "a0124683aa88cd7da886da70c65796c5ad84eb3751e356e9b2aa8ac249cf0bf9"
},
{
"name": "wf",
"unicode": "1F1FC-1F1EB",
- "digest": "62627702e3e3768808c12f153a527ffcc492ad74d8cdc1858cfde971efd0c8ee"
+ "digest": "a0124683aa88cd7da886da70c65796c5ad84eb3751e356e9b2aa8ac249cf0bf9"
},
{
"name": "flag_white",
"unicode": "1F3F3",
- "digest": "96307e3a28e92d1e7147a06f154ffc291ee3cd1765cf8b7bfb06412294112559"
+ "digest": "d9be4b7ceb8309c48f88cfd07a9f7ce6758ea6e620e73293cf14baec03ca381c"
},
{
"name": "waving_white_flag",
"unicode": "1F3F3",
- "digest": "96307e3a28e92d1e7147a06f154ffc291ee3cd1765cf8b7bfb06412294112559"
+ "digest": "d9be4b7ceb8309c48f88cfd07a9f7ce6758ea6e620e73293cf14baec03ca381c"
},
{
"name": "flag_ws",
"unicode": "1F1FC-1F1F8",
- "digest": "0c95271d0f4b23f0d215ee0fba05cf08ecb70665d4c028e17463ecda2754b164"
+ "digest": "53addd0dc304a3c8893389ed227986ef2431828b8c071926aa09f9efd815b649"
},
{
"name": "ws",
"unicode": "1F1FC-1F1F8",
- "digest": "0c95271d0f4b23f0d215ee0fba05cf08ecb70665d4c028e17463ecda2754b164"
+ "digest": "53addd0dc304a3c8893389ed227986ef2431828b8c071926aa09f9efd815b649"
},
{
"name": "flag_xk",
"unicode": "1F1FD-1F1F0",
- "digest": "713aa7d228e96f4a06d58d1fb8c2a55296c3e56842f8177ca936f3e09f50da1e"
+ "digest": "eba1a832e489e1c2734e773e685df5d128271fa5559d23c060e68be067bf6469"
},
{
"name": "xk",
"unicode": "1F1FD-1F1F0",
- "digest": "713aa7d228e96f4a06d58d1fb8c2a55296c3e56842f8177ca936f3e09f50da1e"
+ "digest": "eba1a832e489e1c2734e773e685df5d128271fa5559d23c060e68be067bf6469"
},
{
"name": "flag_ye",
"unicode": "1F1FE-1F1EA",
- "digest": "3bb65bae9c913357bcae8b8b5878efc9e194ca308442ab69639c29716b49f078"
+ "digest": "edfa14266785042b6d5fe0f64fafa630b16a3ee7d010501de7cc8554c959afb0"
},
{
"name": "ye",
"unicode": "1F1FE-1F1EA",
- "digest": "3bb65bae9c913357bcae8b8b5878efc9e194ca308442ab69639c29716b49f078"
+ "digest": "edfa14266785042b6d5fe0f64fafa630b16a3ee7d010501de7cc8554c959afb0"
},
{
"name": "flag_yt",
"unicode": "1F1FE-1F1F9",
- "digest": "f86c86f4c194610a3af78971fcf221ad97b9499d08f6d64476e417a2f52a611e"
+ "digest": "472ebc676b5d31dec2ac5e02ce69014a3dd94609d30a95f39f3a752f49c85e8b"
},
{
"name": "yt",
"unicode": "1F1FE-1F1F9",
- "digest": "f86c86f4c194610a3af78971fcf221ad97b9499d08f6d64476e417a2f52a611e"
+ "digest": "472ebc676b5d31dec2ac5e02ce69014a3dd94609d30a95f39f3a752f49c85e8b"
},
{
"name": "flag_za",
"unicode": "1F1FF-1F1E6",
- "digest": "4dd4fa49a01fdcfc7c1c099a7869e0e9acba83a6a3debf6c8505ada4c796b872"
+ "digest": "dad162942a43392b4cff6929bd5cbf58c382a03dbc0e552f03c07ad2d8ff08ce"
},
{
"name": "za",
"unicode": "1F1FF-1F1E6",
- "digest": "4dd4fa49a01fdcfc7c1c099a7869e0e9acba83a6a3debf6c8505ada4c796b872"
+ "digest": "dad162942a43392b4cff6929bd5cbf58c382a03dbc0e552f03c07ad2d8ff08ce"
},
{
"name": "flag_zm",
"unicode": "1F1FF-1F1F2",
- "digest": "ab6790d89875447de3d1c7f4713b102761bc3e9afdd714b818689e175ca03011"
+ "digest": "1521ecaf1d1fdc8c15f0c96a6b04e6d4050f26f943a826b3d3d661f6ded6d438"
},
{
"name": "zm",
"unicode": "1F1FF-1F1F2",
- "digest": "ab6790d89875447de3d1c7f4713b102761bc3e9afdd714b818689e175ca03011"
+ "digest": "1521ecaf1d1fdc8c15f0c96a6b04e6d4050f26f943a826b3d3d661f6ded6d438"
},
{
"name": "flag_zw",
"unicode": "1F1FF-1F1FC",
- "digest": "9d39b934fe922174b2250f2cd1b174a548d2904091d3298f35b7cc59fbceb181"
+ "digest": "46d05b597c5c77c8e2dc7bd6d8dd62ebca01bc9c9dc9915dafe694ca56402825"
},
{
"name": "zw",
"unicode": "1F1FF-1F1FC",
- "digest": "9d39b934fe922174b2250f2cd1b174a548d2904091d3298f35b7cc59fbceb181"
+ "digest": "46d05b597c5c77c8e2dc7bd6d8dd62ebca01bc9c9dc9915dafe694ca56402825"
},
{
"name": "flags",
"unicode": "1F38F",
- "digest": "c3f4a66786e524a5562919afcba9486113091ed205f1342e91d2f6439845ad61"
+ "digest": "f860aa4df587cf140c3e9735bbd101e9fd5a1bfcea42e420d85ac0a9877fa21d"
},
{
"name": "flashlight",
"unicode": "1F526",
- "digest": "5f641b8fd1c7f1dcd43ec3b1ef78d14ef9929d723789c5567aca8b95d3d39803"
+ "digest": "e929bbe76e0fd2dc5bd6476858a0bbc717fd21467710435d35d80efb38033d73"
},
{
"name": "fleur-de-lis",
"unicode": "269C",
- "digest": "d6ddeeea355ed55103b7fc65ac1ee0dbaa79d01e0d136b265363a6b92284c073"
+ "digest": "ebf49007f367dc05580e9dab942e93e9dda12fa1dc2caa410ac7f8d8cd55d2a3"
},
{
"name": "flip_phone",
@@ -5322,7 +5322,7 @@
{
"name": "floppy_disk",
"unicode": "1F4BE",
- "digest": "e987961ca516032a90942ef6c398836f2da68a5981714bd172acfe7b0e369d0a"
+ "digest": "4ee0b5bba41b9e301ed125d3ee1c263bef171ca499e6e1b89276b09af2bc03a0"
},
{
"name": "floppy_white",
@@ -5337,22 +5337,22 @@
{
"name": "flower_playing_cards",
"unicode": "1F3B4",
- "digest": "451f361050b96ba9ed8dc5b64c8a90c1316fd9b83fb818152881a54e100eea6c"
+ "digest": "edba47c2e3051b2c7effd98794ec977174052782edcb491daec82a2b0d853869"
},
{
"name": "flushed",
"unicode": "1F633",
- "digest": "39cf51f9dec2a910c66ecd39a7bd616fea09d67e81801e57e84f03ed1e917750"
+ "digest": "e759d46bab92af5494d78b6c712c06568759afe397e7828ca0a0de1e3eab0165"
},
{
"name": "fog",
"unicode": "1F32B",
- "digest": "da6fdb9b682ed9a3368adcd7531f1a29e22755a620e3cca163fc3f33a6a78107"
+ "digest": "0cbd4733961d30fe0f40f95dd1f37254aebbef26f82dd18ad2000e799eb2898e"
},
{
"name": "foggy",
"unicode": "1F301",
- "digest": "b599f3178db289c6e30017f3f0a9d30b00a75417057c7a10c0c9eedac78edbf1"
+ "digest": "bc3631a4e9e8473b92e842008937add2cd9ffad5b7d772ce759fb5ff6c0e3dca"
},
{
"name": "folder",
@@ -5372,52 +5372,52 @@
{
"name": "football",
"unicode": "1F3C8",
- "digest": "834fe5f431d6aa8ef1186aa79e71f813393535d273483b6af4cc4bdb8380e5b4"
+ "digest": "ebd790471c3a28d3077818e3b31d915ffe443e06e299bc5cf0dd2534d080634c"
},
{
"name": "footprints",
"unicode": "1F463",
- "digest": "60dc938f6769ea21b05b5afcc481d3ddacf1f565e04f33310b271d5422e7ceb9"
+ "digest": "85bbf2bc0ae8e6259d83a06f513600095d7fcfc44372670f5b2405d380b78811"
},
{
"name": "fork_and_knife",
"unicode": "1F374",
- "digest": "7e07c9dc555d172fa2eaa41cefd8d46d9624be0137aff196dd003a8a82610ec3"
+ "digest": "f228accd36ddccb4ec636207c19d7185191ec79723b780a1bd5c3d00a4b1ef3b"
},
{
"name": "fork_knife_plate",
"unicode": "1F37D",
- "digest": "b4081b9edea6cdab5112fdd17535051ba17710953013f5020c7c40f84a1e3247"
+ "digest": "ec6be99dac8efd3d145807fa60d2b6d8f6d3c02cb95552b55cc0fac39a4db48e"
},
{
"name": "fork_and_knife_with_plate",
"unicode": "1F37D",
- "digest": "b4081b9edea6cdab5112fdd17535051ba17710953013f5020c7c40f84a1e3247"
+ "digest": "ec6be99dac8efd3d145807fa60d2b6d8f6d3c02cb95552b55cc0fac39a4db48e"
},
{
"name": "fountain",
"unicode": "26F2",
- "digest": "0acdca5e8f6d745a8d582d96012ec8fc55b9f5447e657ebfd998a4e332d99322"
+ "digest": "87043f9256e1d4615159307fcfd21bf6ae2aba0bada7de2bd50d7d6f2ab82395"
},
{
"name": "four",
"unicode": "0034-20E3",
- "digest": "36bd4ea6e2ae689835a79f8e60466eccd62fce7e91e84ed768cffd87dac628dd"
+ "digest": "c2c82a966bbb599aae557d930a4fc42604f2081aa45528872f5caf4942ee79d9"
},
{
"name": "four_leaf_clover",
"unicode": "1F340",
- "digest": "12ee2343df25bbd9077fdc12314c1edb51c0cdb556af7e22590e8a578ef57f17"
+ "digest": "ebee16e86bc9be843dfc72ab5372fb462f06be4486b5b25d7d4cac9b2c8b01c8"
},
{
"name": "frame_photo",
"unicode": "1F5BC",
- "digest": "6ff21063063989c6ae7dd69f4d6a781c676f9dba380d8e6f1dbac5d53b24f349"
+ "digest": "d5074f748a15055ec1fb812c1e5e169e6e3cc73c522c54be1359b0e26c0fc75c"
},
{
"name": "frame_with_picture",
"unicode": "1F5BC",
- "digest": "6ff21063063989c6ae7dd69f4d6a781c676f9dba380d8e6f1dbac5d53b24f349"
+ "digest": "d5074f748a15055ec1fb812c1e5e169e6e3cc73c522c54be1359b0e26c0fc75c"
},
{
"name": "frame_tiles",
@@ -5442,122 +5442,122 @@
{
"name": "free",
"unicode": "1F193",
- "digest": "c1d9172a656717f78d941303c5da8790c6cd9827838d8f7dc3719afb53bcab80"
+ "digest": "9973522457158362fc5bdd7da858e6371e28a8403d1ef9e4b6427195c7f72cfa"
},
{
"name": "fried_shrimp",
"unicode": "1F364",
- "digest": "c0c19e95f2c38f6cf870920bf3c2d4d69c36ea6e7dc9a5c45c3e8b285269d40a"
+ "digest": "0792bdc4484852de970c8f43bc3a1a339dc0e48090ec77d6de97cbfcdd17f9e1"
},
{
"name": "fries",
"unicode": "1F35F",
- "digest": "0f546534684de29d319cbcbab4162acb321c4f8f3202fe17d69e1894ab7c8195"
+ "digest": "47915aea67251d358d91a0e4dc3dcc347155336007d6b931a192be72a743b4e9"
},
{
"name": "frog",
"unicode": "1F438",
- "digest": "6a417757fa6ee39e7a277cbd53c690ff88af0b1d76728d56f9bc645cb628aeb7"
+ "digest": "d024b2ce771df64040534fb0906737d18b562bc3578dee62c2f25ec03c7caffd"
},
{
"name": "frowning",
"unicode": "1F626",
- "digest": "fb39f5c2aea98054adb02a3a0ac34a2e38d83f32cd590e9d2449e06a9702f2f5"
+ "digest": "c01af48537b0011d313d8f65103e1401fce4f5c0269c68e0e9806926c59acc44"
},
{
"name": "anguished",
"unicode": "1F626",
- "digest": "fb39f5c2aea98054adb02a3a0ac34a2e38d83f32cd590e9d2449e06a9702f2f5"
+ "digest": "c01af48537b0011d313d8f65103e1401fce4f5c0269c68e0e9806926c59acc44"
},
{
"name": "frowning2",
"unicode": "2639",
- "digest": "7bb6c682a6c9f98bf3a5ae986e317fd26d1af497c857500deec2f06b6a3af5da"
+ "digest": "6568ee393b950c852d440112e86908c456b89fb7780e27778c5fcec168373fbf"
},
{
"name": "white_frowning_face",
"unicode": "2639",
- "digest": "7bb6c682a6c9f98bf3a5ae986e317fd26d1af497c857500deec2f06b6a3af5da"
+ "digest": "6568ee393b950c852d440112e86908c456b89fb7780e27778c5fcec168373fbf"
},
{
"name": "fuelpump",
"unicode": "26FD",
- "digest": "9cbb2646c93b255bd3de87dc01aa1193ab96e39a3013975d250472ab8aae61d6"
+ "digest": "105e736469f19911b8bab4ab6d29f949ded4b061b54e3dd763726577d6453095"
},
{
"name": "full_moon",
"unicode": "1F315",
- "digest": "0b4f08ef2089397ead034b444a60e6e9810073454581b52a46b2369e3b9cd5f9"
+ "digest": "aaa87f4676a5aaa29c1b721a3b582e89db6c1f35a25c52e4b480bd193ef39c43"
},
{
"name": "full_moon_with_face",
"unicode": "1F31D",
- "digest": "a371cb9e1f28a7db739dd058234642a2e333dff4b6df9882df85a6d984e4b5e8"
+ "digest": "05c4b9c339fcdf81ae67027641522baa99c370d87873ff4c8133b8349e627e33"
},
{
"name": "game_die",
"unicode": "1F3B2",
- "digest": "6584909a4348c350c04417421b63eace1245087f7d239051b30a0cd37fe929f9"
+ "digest": "00d19ce8e21dba2cdfeb18709fa8741f3af9d6207f81d5657b68e05e64f105a8"
},
{
"name": "gear",
"unicode": "2699",
- "digest": "b0ff5fd007daa366a9eecb7422dbeb8a973e123a04267b88fef96c7453238294"
+ "digest": "c5ba354c0f7a36dce95477091984e352ecc59af8c9f26a94ad8e296dc042b9de"
},
{
"name": "gem",
"unicode": "1F48E",
- "digest": "d75d854f35975e4e291c3b9fcaf8437467f6d7eb27b29e2d7c0f0038fc666fe2"
+ "digest": "180e66f19d9285e02d0a5e859722c608206826e80323942b9938fc49d44973b1"
},
{
"name": "gemini",
"unicode": "264A",
- "digest": "392abe62872736a0bf92979a8c25a814985d0ff0a08dc7ab2a5c058aeda7e685"
+ "digest": "278239c598d490a110f1f3f52fc3b85259be8e76034b38228ef3f68d7ddd8cdd"
},
{
"name": "ghost",
"unicode": "1F47B",
- "digest": "f084b14483476e2d07563840f8c33b46da9c17f791da07fde3acffeb77342947"
+ "digest": "80d528fcf8ef9198631527547e43a608a4332a799f9e5550b8318dec67c9c4d2"
},
{
"name": "gift",
"unicode": "1F381",
- "digest": "c9a2ae6ea05c02e78e9567dcbd971701a2f869eb46c62d85cef23d0834388d8c"
+ "digest": "4061a84a59f0300473299678c43e533341eb965db09597fffc6e221fd7b77376"
},
{
"name": "gift_heart",
"unicode": "1F49D",
- "digest": "e0c5aacf1ce89117d86b148f10a02dc18fe0cd22a75fbf6f0f88f2fad3ca80fe"
+ "digest": "5420199b515b9b32c964a3c19d87e07461639e3068a939dae26c6436335c0cee"
},
{
"name": "girl",
"unicode": "1F467",
- "digest": "0758cbc4cbc7d72d6df8f66fc3a6b2b283c6634b053e59d61c6cac44cf8bffda"
+ "digest": "8d2d0b72a91e6e44921b71030ffc4c89c0f50f1364787784afe1e7e568cf1bc6"
},
{
"name": "girl_tone1",
"unicode": "1F467-1F3FB",
- "digest": "7afdece55cb64e8056e2202de8c17b66ddb616f224ac374ec9a160d06b3138cc"
+ "digest": "bda12a6b38994a578ee65166bbdd93ea04df4101697b52ed236de8d687df09de"
},
{
"name": "girl_tone2",
"unicode": "1F467-1F3FC",
- "digest": "c160aa65fee70ad52930d01246ac9f282ff6abf1d93c5cc5b299fc257ee81db1"
+ "digest": "de7a0925c30b7181a289f71b1a849c1b7751ee8c104e8f2029bd9c2fe3f91c64"
},
{
"name": "girl_tone3",
"unicode": "1F467-1F3FD",
- "digest": "b8a5687cd637855a41b8c7dc686f0e69fda379875408cd269f1b330a805c72f4"
+ "digest": "e41272816db0e642d003dce7cb262e1593a592251f46729f7830f4515149e1f2"
},
{
"name": "girl_tone4",
"unicode": "1F467-1F3FE",
- "digest": "a9cf743936b733634f323790a1abe3a410601b6841484baebea484b392f4e98e"
+ "digest": "8d6a4513ecbf08408c0ecc5336767777a2216f7a19437faf9e51f65101822469"
},
{
"name": "girl_tone5",
"unicode": "1F467-1F3FF",
- "digest": "c902170e67b81eee35eeefb6a5c62c6109cb423dcae88d4e036ddd50b240c072"
+ "digest": "f55e4b16a41b6f5e3c817a301420360ba4486e4e82e1092a56a3e3cc4069087d"
},
{
"name": "girls_symbol",
@@ -5567,172 +5567,172 @@
{
"name": "globe_with_meridians",
"unicode": "1F310",
- "digest": "945646de3d8f057760fe374494a253d9a6aa8a132309154b0a5bdbffb5b20c3f"
+ "digest": "725bebeb3c09a9e3701ebe49e672dcfbf2b73575e05f0821263511577b013b75"
},
{
"name": "goat",
"unicode": "1F410",
- "digest": "f99cbc6755d119cb5c1dce08cabd20871f98d009bb773da4a146dae60476a235"
+ "digest": "d07e384d08529ddcaddd2710f2ad913e5665dc15d5f99c28e16dadd245a111e8"
},
{
"name": "golf",
"unicode": "26F3",
- "digest": "74a7876d185f8ff6a6533e4db2e1eb787119b2f8d8b07c36d99ec3163fb48485"
+ "digest": "eed79364754eec97855e3c7b584f347ae139d9ddb4eb7fb66c00867610b8f1c1"
},
{
"name": "golfer",
"unicode": "1F3CC",
- "digest": "6458295a5e4a6e4323c32a7f1f7182fb2d3918083839efc380d995860ce360b1"
+ "digest": "7d7ecc6e226596f646030a4109c2b0001ef0cc690e4863e450bf5d29e7a90344"
},
{
"name": "grapes",
"unicode": "1F347",
- "digest": "7f6873d65180ab476f49d207ac2d1f7dbaf6c8b0b561d50b64325e192cf97a86"
+ "digest": "74d1a09ab411234a84d025a2e717e7ec5791bc02aad29853896d21c0f0283c50"
},
{
"name": "green_apple",
"unicode": "1F34F",
- "digest": "effc3fe60f2ab704a034c794bfccfa023b41332f8f16ca44cc8ea41698f03873"
+ "digest": "457490e9b2b20894f50768262d63f1021717079da104d4847076b3fa779e9a21"
},
{
"name": "green_book",
"unicode": "1F4D7",
- "digest": "6652c4d2ccfa4a287a5d45007bd06cadc16d34b0a1ca4b6b13b46f976c8d8319"
+ "digest": "370f635b200efe5e4a9f17da58bd22500e258e61d17795cef375f19c9a45468f"
},
{
"name": "green_heart",
"unicode": "1F49A",
- "digest": "f4bcb660a1d3cf3692238359d8b9de9a725a9af81f166253e487d61b8ccf9d86"
+ "digest": "f71e30416d9019873f2ed38ef375c48386424ff60b5a07b89b15dc9e0a3970f9"
},
{
"name": "grey_exclamation",
"unicode": "2755",
- "digest": "ac8cdab7496d133e7bc9475f2fdb0cf59b3ccba20f2f156c8b693e72b5948078"
+ "digest": "2fa1d356e12c17cc4025e43afb6c3070385f677102a35223302fda46c47a9b03"
},
{
"name": "grey_question",
"unicode": "2754",
- "digest": "c173e1b2a16ab62b0abd7a58deb7a6df709b072d30d001627b92d0123a3a3e4a"
+ "digest": "e1035bcbf0f66d238ef478ba451f5cf2c51627fbf101ed03bad3b2bf38db8aa2"
},
{
"name": "grimacing",
"unicode": "1F62C",
- "digest": "8c54b73f5d2c1c6347e2c0ab01616519e0fb34490daa9c36664d442c6851c57e"
+ "digest": "2cedad13b8b2a1d4385ca6fa88a251eb7757a4c65dd6d362267864a01247846b"
},
{
"name": "grin",
"unicode": "1F601",
- "digest": "916eabdabd8b7ca698e638bbbd14affff97464ec11a3b59c0cb96cd7705600d8"
+ "digest": "634b2f37e32e57ed6edc7f371993a92e34137dd21ba393de5227cfbbe2422815"
},
{
"name": "grinning",
"unicode": "1F600",
- "digest": "3d8665c03f272ca3063e96145989926355a7ac315ed1a032d30fcefa6f0c3923"
+ "digest": "cef76aa41771db9fd1d6bd9b4233c22c1fb1931494af54cab29e6347ed9b678d"
},
{
"name": "guardsman",
"unicode": "1F482",
- "digest": "ebbd29fa138005232d64fca4a8ec015d097fa14e6ded57b35ac257b4570b3c36"
+ "digest": "17bc7fad6b8c8dbd015bb709380d129f8b8e1e971062d15e6ab0b2e63e500564"
},
{
"name": "guardsman_tone1",
"unicode": "1F482-1F3FB",
- "digest": "b6082c8fee5dbc3ce2540f3939d5e344b5366c9f07827345facaba438e7017ff"
+ "digest": "c531ecb101bdf9ce1db18e1567882e6db927410237100b0a2492a1401860246e"
},
{
"name": "guardsman_tone2",
"unicode": "1F482-1F3FC",
- "digest": "2b813afe1c2bbdaf9a47493393a0e6c400a16e453ed25a9a9c0035197927b56e"
+ "digest": "602168c5204af0f1de8b4aa5863b192ef20c19d263999377aa5eb60f98311732"
},
{
"name": "guardsman_tone3",
"unicode": "1F482-1F3FD",
- "digest": "49b2fa1ad0bc50a5ef6d73fb140aa1876506b9ebb9d45782ccb8dbb6818f8dde"
+ "digest": "d0a85de46dd02c7bd6cb14bff0f22d2db9083d4b171a8806c83363b49f3dd9ef"
},
{
"name": "guardsman_tone4",
"unicode": "1F482-1F3FE",
- "digest": "a584e1e3a8ad7be4871a6bdb7996d4f649abeaa77eb5d1cae998058d8b23ca0f"
+ "digest": "1c9d4d72b6b50bdac8271613b6d2a38340ec2067bc344e8ee2a3c863fd5c23a1"
},
{
"name": "guardsman_tone5",
"unicode": "1F482-1F3FF",
- "digest": "e853b67ee13fda99e98f47083529ca80c404df1b19352c78b9c69850eb8f2c76"
+ "digest": "9899a796d01842e495d716fbe737a16d85724f7d3e23f50807ec2bc70f057318"
},
{
"name": "guitar",
"unicode": "1F3B8",
- "digest": "8c041b961649cc5917f56f2fb543f9a5280724647ed2fc67bc94a05eff9da805"
+ "digest": "a1027ceae4dd3ea270740587c9d373329e5677e375c9e00af6ae3275e0b67500"
},
{
"name": "gun",
"unicode": "1F52B",
- "digest": "d7f5aa657cc0ba04d878511820632b89c305a9b4d6c4a4b90ff691dad9906607"
+ "digest": "fc12b577df2283e7b336f23774f9cfe5b79f1d26ddd28a64a560519b28d94ca5"
},
{
"name": "haircut",
"unicode": "1F487",
- "digest": "369dbab1b138c31d3eca04c950fdab4ec9f085272268c241f100d44e7b0f229e"
+ "digest": "b243a04f5ca889accd45e7abe095ac5caa92274ed95103f5966a36b415fff412"
},
{
"name": "haircut_tone1",
"unicode": "1F487-1F3FB",
- "digest": "c56f32d7c1d8a92d22429133f87f31a159818939cfdc570cb48b6d243cc58cf2"
+ "digest": "a58d0cff1427b80dfd7a9ea5267b4a181e9faaac6a51a0165db522f668b4cf91"
},
{
"name": "haircut_tone2",
"unicode": "1F487-1F3FC",
- "digest": "e916e040ffb8e869e930d1256343af2ad2bbaa683f01a11564d0777019944bec"
+ "digest": "675083ff40001405f8de99268477d50dd8594ff6ca40ddfd442dd42ad76e8216"
},
{
"name": "haircut_tone3",
"unicode": "1F487-1F3FD",
- "digest": "f07cdfbea964ac42a9a050f832107ef0f2fa8115b27689f93d1be954de07b7c1"
+ "digest": "70d7581e49c315a3771dd61a3713229886db32aaaeb3af078a69cc042f809150"
},
{
"name": "haircut_tone4",
"unicode": "1F487-1F3FE",
- "digest": "32ec7f5e999f7c43676768c8320ffaa346c713d340a94b948b1f564b345a2d11"
+ "digest": "ec5e3e909eb3bc375ef9cc0fe0e0f90b33f44f273ada91ccf415bbc43b8ffbfc"
},
{
"name": "haircut_tone5",
"unicode": "1F487-1F3FF",
- "digest": "5aad997d09e7975700927906d41a10bae774356ccddbe5197980bde670272262"
+ "digest": "7c89739ee458546a808fded7f96d9354c47a76883ebb262d5f5abeafd021260e"
},
{
"name": "hamburger",
"unicode": "1F354",
- "digest": "24ebae9a69cf283ab198499cb38d0cdcd82bac74c8e8d1e769ad78eb320a4294"
+ "digest": "48204235238bd89d3a69f319f65135102f3d6b181eec241d4d86b302bbffa9bf"
},
{
"name": "hammer",
"unicode": "1F528",
- "digest": "a43a66b0efdc4cd2c84fd0ccc2cb8e9ede1f89c5d62eefa6ae521d3aed9d81b3"
+ "digest": "d0e7830539d935fcd82820c4e0c1d724f0756dfc83a51171fe0f4b36b69fac42"
},
{
"name": "hammer_pick",
"unicode": "2692",
- "digest": "2e4fe33406ca03fbb0df1596d63e903d8ee6bd78ecc3ec38a67dd2cecbc584e2"
+ "digest": "aa0445f43bca58d17afa7f3577632ca7775f5a28336385b3020b268b15b18142"
},
{
"name": "hammer_and_pick",
"unicode": "2692",
- "digest": "2e4fe33406ca03fbb0df1596d63e903d8ee6bd78ecc3ec38a67dd2cecbc584e2"
+ "digest": "aa0445f43bca58d17afa7f3577632ca7775f5a28336385b3020b268b15b18142"
},
{
"name": "hamster",
"unicode": "1F439",
- "digest": "f47da088ff5792532a382b6e3a47d2dd7c5e6fc19abd5ff6c5ba3ce420b4192e"
+ "digest": "a7e7582e8b1bccd5b7df27ccb05e353a3f0e39bdeb40877732706b9d74a70de1"
},
{
"name": "hand_splayed",
"unicode": "1F590",
- "digest": "a43e52f7cdec5e9d51497888b0988d7bbd42846ad7e492b196293fbce576d197"
+ "digest": "c51a30cb7e575d29ffed16780a6c95ae3f300b8ac523012f4a6e116d68c1fd15"
},
{
"name": "raised_hand_with_fingers_splayed",
"unicode": "1F590",
- "digest": "a43e52f7cdec5e9d51497888b0988d7bbd42846ad7e492b196293fbce576d197"
+ "digest": "c51a30cb7e575d29ffed16780a6c95ae3f300b8ac523012f4a6e116d68c1fd15"
},
{
"name": "hand_splayed_reverse",
@@ -5747,52 +5747,52 @@
{
"name": "hand_splayed_tone1",
"unicode": "1F590-1F3FB",
- "digest": "73cceec7117280d330f8a149979190f0f355dd8d0a92821be89fb70344bb8dfe"
+ "digest": "c31fb44a982ed8808e1c311ec1b0b9c5afcb47f16bb1fc731dc483adf8f0d049"
},
{
"name": "raised_hand_with_fingers_splayed_tone1",
"unicode": "1F590-1F3FB",
- "digest": "73cceec7117280d330f8a149979190f0f355dd8d0a92821be89fb70344bb8dfe"
+ "digest": "c31fb44a982ed8808e1c311ec1b0b9c5afcb47f16bb1fc731dc483adf8f0d049"
},
{
"name": "hand_splayed_tone2",
"unicode": "1F590-1F3FC",
- "digest": "b06fac698128f4c3a7b8ea56e8bc4de088bb5461aa0f9c84553f16b43d347145"
+ "digest": "56a236881184e9ffad54613fa08a67368c432af738f5254fb1cd87b20368acdf"
},
{
"name": "raised_hand_with_fingers_splayed_tone2",
"unicode": "1F590-1F3FC",
- "digest": "b06fac698128f4c3a7b8ea56e8bc4de088bb5461aa0f9c84553f16b43d347145"
+ "digest": "56a236881184e9ffad54613fa08a67368c432af738f5254fb1cd87b20368acdf"
},
{
"name": "hand_splayed_tone3",
"unicode": "1F590-1F3FD",
- "digest": "a94ee9a2f8cdec6d2f7dd6887d1c7b8e064fcad63030c2c7c001742d72b5603e"
+ "digest": "9242ca97dfd2bbc1947228f6535029afb31f8feb72c14ff4b7f2deea30217425"
},
{
"name": "raised_hand_with_fingers_splayed_tone3",
"unicode": "1F590-1F3FD",
- "digest": "a94ee9a2f8cdec6d2f7dd6887d1c7b8e064fcad63030c2c7c001742d72b5603e"
+ "digest": "9242ca97dfd2bbc1947228f6535029afb31f8feb72c14ff4b7f2deea30217425"
},
{
"name": "hand_splayed_tone4",
"unicode": "1F590-1F3FE",
- "digest": "501792b4126c6f32e755accee0fc8b4d1915e1d36c4ceaa40f3bd0066efe76c3"
+ "digest": "43348d9fd3d43b3c45cebaf663bf181bcad3b6df841a5aeed838180db2cdd481"
},
{
"name": "raised_hand_with_fingers_splayed_tone4",
"unicode": "1F590-1F3FE",
- "digest": "501792b4126c6f32e755accee0fc8b4d1915e1d36c4ceaa40f3bd0066efe76c3"
+ "digest": "43348d9fd3d43b3c45cebaf663bf181bcad3b6df841a5aeed838180db2cdd481"
},
{
"name": "hand_splayed_tone5",
"unicode": "1F590-1F3FF",
- "digest": "22ed533d587cf44f286e2d6ad77be20b4b5f133c422af4ca51e9af86a75002d8"
+ "digest": "4b3a0aba7829772fec09f26d6facc19a2f822d2998015297b18b5cab85190ee2"
},
{
"name": "raised_hand_with_fingers_splayed_tone5",
"unicode": "1F590-1F3FF",
- "digest": "22ed533d587cf44f286e2d6ad77be20b4b5f133c422af4ca51e9af86a75002d8"
+ "digest": "4b3a0aba7829772fec09f26d6facc19a2f822d2998015297b18b5cab85190ee2"
},
{
"name": "hand_victory",
@@ -5807,7 +5807,7 @@
{
"name": "handbag",
"unicode": "1F45C",
- "digest": "f1e2822c67f659b52c76821dd9db001332215a8566fc1846c89b6019c9758038"
+ "digest": "45410a3eed0c2e3f68748d7649fa9e33a90f4e80d5291206bdd0b40380c6da45"
},
{
"name": "hard_disk",
@@ -5817,67 +5817,67 @@
{
"name": "hash",
"unicode": "0023-20E3",
- "digest": "5bd5c7180485fa71accdec5378bdc196ce0602f594f91e4eadc1e7514d5d0f90"
+ "digest": "01c8b577953010bff0c20f797c2c96ab5d98d4e6ac179c4895a78f34ea904655"
},
{
"name": "hatched_chick",
"unicode": "1F425",
- "digest": "7995c3eb503a8b9662694eba80a9b551216473a31928091e35cd6ebc21cee083"
+ "digest": "006571b9e9e839ec9fcb1a911b935c8ca71eb8bcdce9775bee6a2a4c7c927277"
},
{
"name": "hatching_chick",
"unicode": "1F423",
- "digest": "22905b42fa65dbc9aad8940d2db13691cacc62014f54e0960978ee0002178e1b"
+ "digest": "fd7f69fa186407f80de59dec5116e318325a5743ee0e8bba1db541f1e57e7f74"
},
{
"name": "head_bandage",
"unicode": "1F915",
- "digest": "d690b740ff4f58e89dfc764c6411a4e84cfedffd7694eb5efa839a642dbabd08"
+ "digest": "d09019a73e203b38cc43729a96163147de88e09eab8adb073888e55366854c72"
},
{
"name": "face_with_head_bandage",
"unicode": "1F915",
- "digest": "d690b740ff4f58e89dfc764c6411a4e84cfedffd7694eb5efa839a642dbabd08"
+ "digest": "d09019a73e203b38cc43729a96163147de88e09eab8adb073888e55366854c72"
},
{
"name": "headphones",
"unicode": "1F3A7",
- "digest": "219da138032c01c97a94f02b211049418191a3beb3d159804b9033f5916fd3c8"
+ "digest": "34f9d5598158d5d6f978a5ea5c5aa9948bb2990625565a3afad7710f864fbe2f"
},
{
"name": "hear_no_evil",
"unicode": "1F649",
- "digest": "8120060238eaca645809dd113862a144f10395afcb3837ab60c0f04009b49a2f"
+ "digest": "53b030b6d6f4ed1a734fa7d48b46f42eb1b2b01653202c1838b742082f08c4bf"
},
{
"name": "heart",
"unicode": "2764",
- "digest": "a646a25a36f431cadc7e56afd1a4d1b7cbae5292a25d7783bd31462d0d3d719b"
+ "digest": "92be652ec3e50c6e7393440b5d52b88a367f98a28dffe12660095ed3253aa6c0"
},
{
"name": "heart_decoration",
"unicode": "1F49F",
- "digest": "a83989669347c98cb74065d4f0befedbc37f82c91214e773245cb6810ab359b4"
+ "digest": "6ec5bbf3aa75c6f43eb3dc05e9204366936e8b6b4219310bacdc2fc45f51e245"
},
{
"name": "heart_exclamation",
"unicode": "2763",
- "digest": "9751c89dcf10805f2011949ff3ddcb6bcb13de8c32ae5de9e03955e8a4235df2"
+ "digest": "5985ea4d82232a2a07052a59db268aed9ac943895d0c82f637595bb5386329a6"
},
{
"name": "heavy_heart_exclamation_mark_ornament",
"unicode": "2763",
- "digest": "9751c89dcf10805f2011949ff3ddcb6bcb13de8c32ae5de9e03955e8a4235df2"
+ "digest": "5985ea4d82232a2a07052a59db268aed9ac943895d0c82f637595bb5386329a6"
},
{
"name": "heart_eyes",
"unicode": "1F60D",
- "digest": "335ea73efca4824e623a5a51ccdb494c8b1f5f10b4139b39b250a2a771876b0d"
+ "digest": "0eff616517a6252ec89d47d9b4ad85589bcf2bdc7f490578934350acb84b2fcc"
},
{
"name": "heart_eyes_cat",
"unicode": "1F63B",
- "digest": "9346b85afb80f7b498cc255426ea15a287f81d8fb3c26dab61337635f439d3ce"
+ "digest": "8a1f28b97d661ca4cff5ee13889ca61b5fa745ccb590e80832b7d7701df101d6"
},
{
"name": "heart_tip",
@@ -5892,257 +5892,257 @@
{
"name": "heartbeat",
"unicode": "1F493",
- "digest": "cd6921ce55c155873220a09416d695c4bcca1556007066d6d185e93d6561e825"
+ "digest": "c9ec024943439d476df6f5ec3a6b30508365a7af3427671a80de3ef2f4f95ffe"
},
{
"name": "heartpulse",
"unicode": "1F497",
- "digest": "f869357b9e678d9671ec38c569fc88efec48006c159b69297277cee795dc4dc9"
+ "digest": "281d8aebfea37db5b7fe82d9115be167006881fe29ab64a5b09ac92ac27a2309"
},
{
"name": "hearts",
"unicode": "2665",
- "digest": "17dc9b2941561f58ca0f04d0754b1eff3490b63b17241580b3d4aa4638fa85e8"
+ "digest": "271429d12c40be921897005b7bdd08f9518960af1e1e6f56bb0060f1f183651e"
},
{
"name": "heavy_check_mark",
"unicode": "2714",
- "digest": "b5fa24f6e0f1dcbd6278e9125154522f2efd79e6dd0836ccb792a1f3aeeff2b2"
+ "digest": "e347728e1290eb9e7b0742d628e2fd124fc049e0774f8a6ddf8e5286e7318718"
},
{
"name": "heavy_division_sign",
"unicode": "2797",
- "digest": "59a6983d788f347c64eecb3df6f7d3b36779d92df6cc811820993ff9e18d77e1"
+ "digest": "c1e8c40f0788f140b1c5fcb81ed9b5ce1bcfa5988bb8140ed2808e9cb7e0d651"
},
{
"name": "heavy_dollar_sign",
"unicode": "1F4B2",
- "digest": "d2e89c54b3fdeda4d1fd4d29454b69dcf750181110894e6e71a40df99c95bfe8"
+ "digest": "7cdeef38348654b93d566e01a48973281cb404a63d0b75b3bad51032887f3f55"
},
{
"name": "heavy_minus_sign",
"unicode": "2796",
- "digest": "dd5ab3722fe49cfdbc5e1fbab5b342dc960de7b412d4fba59d66e06ce3dc3bcd"
+ "digest": "e5335cc6b22abdce49a6127c34269b65a4a6643ddd3253d9baac425089143e7d"
},
{
"name": "heavy_multiplication_x",
"unicode": "2716",
- "digest": "7d77742f91377785675802f40bd8dde9bd1feeb513735760a58ea9bee8a65d44"
+ "digest": "64bbe9e9716a922e405d2f6d3b6d803863a53fac80ff8cd775899971046cb1ca"
},
{
"name": "heavy_plus_sign",
"unicode": "2795",
- "digest": "9aa9dcdbba120a4b485c21f67589609b789c6e3edf08479ff8268fa0db973ad7"
+ "digest": "d0d8ade2020ceb252205180b85c66e665856e6cb505518d395b9913b0b24b746"
},
{
"name": "helicopter",
"unicode": "1F681",
- "digest": "b259ea8d2bdca36766075894da650b1d3ff4c8602259cd0d30cb8214cd585340"
+ "digest": "4bd6fd13650fbe3a19cfffeffe6c21b1cda74bd6af64c5dc5999185e35444bc3"
},
{
"name": "helmet_with_cross",
"unicode": "26D1",
- "digest": "affbe9dd87b87ff9235b4858c59c2a73e9ed30dd5221e5b666b8d7747378a9c4"
+ "digest": "8286107391d44b9cd7fce5dc83bfdebbcdcf5a8214c46a8990732ec40263ed77"
},
{
"name": "helmet_with_white_cross",
"unicode": "26D1",
- "digest": "affbe9dd87b87ff9235b4858c59c2a73e9ed30dd5221e5b666b8d7747378a9c4"
+ "digest": "8286107391d44b9cd7fce5dc83bfdebbcdcf5a8214c46a8990732ec40263ed77"
},
{
"name": "herb",
"unicode": "1F33F",
- "digest": "3c452106b1966f643751bf161fa7d1762a33e6fff381b2109bb53b55c4fdd129"
+ "digest": "9fe8ed65515ede59d0926dcf98f14e2498785e1965610aa0dd56eca9b4bedad9"
},
{
"name": "hibiscus",
"unicode": "1F33A",
- "digest": "268963a1f3cdad9050d9ae31c558e010f33812e3b09bbf9088ba876c033d8b2f"
+ "digest": "c442e8eacbd8727bd154bd39692a9a2a03ea2f674b9670ad8361f78a038afe49"
},
{
"name": "high_brightness",
"unicode": "1F506",
- "digest": "d607f6269d95dd16c2a7932e49ac09e44f4c19e0a34f6c0f21ecb945a2316361"
+ "digest": "35ced42426dcfd5214c2c6c577dce84bb708156433945e6b6adaff7ea530cc57"
},
{
"name": "high_heel",
"unicode": "1F460",
- "digest": "5c320d5954bf4f4dacacddd562c1598ab101731077a6656ac5d2bfd41405483e"
+ "digest": "1e7c7aba50eb1d02cf1d9aa372caca741a6005cf47f68dfa75b7310c3cb18f05"
},
{
"name": "hockey",
"unicode": "1F3D2",
- "digest": "008904c1b8db139215492a6d96c09f2c3eeda769f858a9bbae13f8c54d439d0e"
+ "digest": "2d00fb17baa617e799db8e9b1771cc365bb4545c7633df0123e66e1a6e2ed25d"
},
{
"name": "hole",
"unicode": "1F573",
- "digest": "36bbafa5e89b1410ec74919aaf60b09ac3525a421cb5b475b9bb2f20357db8de"
+ "digest": "8b5539f6f24f09d5d68ffd56be5aa2a8a2f753a8dfbf64892fb02c8f2703e920"
},
{
"name": "homes",
"unicode": "1F3D8",
- "digest": "9980d6dd6cbd23b820747ecac4cb10974dd24b0c94b4acfe21fa87793ad065c9"
+ "digest": "cd512f2b4ce747325607d47da48e083dbfe38a44b85b2522bc372bd105afd25f"
},
{
"name": "house_buildings",
"unicode": "1F3D8",
- "digest": "9980d6dd6cbd23b820747ecac4cb10974dd24b0c94b4acfe21fa87793ad065c9"
+ "digest": "cd512f2b4ce747325607d47da48e083dbfe38a44b85b2522bc372bd105afd25f"
},
{
"name": "honey_pot",
"unicode": "1F36F",
- "digest": "94cb1624491076b5cb145e7a309f91a7be3d4c0bed712af6a51d641eb73edee7"
+ "digest": "f6eec8c32fbd1b461446dc6c5d5031c43e6ee9685dc9b1ea1b839114e48c4eee"
},
{
"name": "horse",
"unicode": "1F434",
- "digest": "624ad9dc9ed7af3f6e1a2f9d4ed483702ae64ed5fbcf5e9918af6bfef24e76f9"
+ "digest": "e377649a9549835770a2a721a92570f699255f88efa646029638eb8ec5f10e3d"
},
{
"name": "horse_racing",
"unicode": "1F3C7",
- "digest": "c2702b7225e9839a789dda7c43f0cc86dced2b4d5d3787116106396633362de6"
+ "digest": "3b98e94e9c028ad85b9a750cc61db5ee3ac23cf5ad9243ea3e996b1f772bad54"
},
{
"name": "horse_racing_tone1",
"unicode": "1F3C7-1F3FB",
- "digest": "a7ed284f9d5cd8a4fe4a09cb91c3f99e5db99c7e31c5f525c14de97b06857d92"
+ "digest": "382d8e4502ed34fc1bbf1779ce483bc2e22b83f89c91746c11a5d7aea656d446"
},
{
"name": "horse_racing_tone2",
"unicode": "1F3C7-1F3FC",
- "digest": "20b4d61b21ee6ba860b029f0ad0e38f5ecb6dd2c774f7b7801fba07ed33f96be"
+ "digest": "198df9973b492ea63e5cfc210dd9591750ccce04a6380adc1dc5b4cb0462a8cd"
},
{
"name": "horse_racing_tone3",
"unicode": "1F3C7-1F3FD",
- "digest": "dd65f7bb96ee44507d26e524202d567d2d7679d571245299a2a84f68bd5def4c"
+ "digest": "a67f95fc92c366750ebad3c4db92982893d67a5ed78163c8cc809ac40d2ab9a3"
},
{
"name": "horse_racing_tone4",
"unicode": "1F3C7-1F3FE",
- "digest": "36afaad218a4c820b19c7c9bbbc187119d47b41273d8f48ab14cc3e32dd7c21f"
+ "digest": "986b1706c4a3395b58a8ae3b7609ffdd4424dfefcbf26c88c8085f4f6379734e"
},
{
"name": "horse_racing_tone5",
"unicode": "1F3C7-1F3FF",
- "digest": "2e0efd501a4471428533ce7909972a49ff045369261c27e4abb97ee2aede2f47"
+ "digest": "66656b5e3d0f43f16f983f9db6214b07aac73b143eeff6475782f98aa5b9ba53"
},
{
"name": "hospital",
"unicode": "1F3E5",
- "digest": "df5c774fa36b2601e6960a7b81cdfac71c1d2d71f04dea88068d1c9043e313bb"
+ "digest": "034573e76df444f5b0eb7aff3a4103e4b49a1813869155ab3ae29a6fc0c6c8a2"
},
{
"name": "hot_pepper",
"unicode": "1F336",
- "digest": "62e4dade3c793f6d83530bd1f60f3e3e26c1e10a41786c3a15f5aec0ff2b8e76"
+ "digest": "0b05777d42698196a10db17d04030175b1dfa772d06288f71d666d5f8d3fddbc"
},
{
"name": "hotdog",
"unicode": "1F32D",
- "digest": "58b829e26b5c4642942898d9c7873cb08e048fd7deaacba8292899d5d895cb2b"
+ "digest": "7a25bbd1a7531fd34a22c654c0931d9e74bea2bbe7baa9f9cbd88f43baa79fb5"
},
{
"name": "hot_dog",
"unicode": "1F32D",
- "digest": "58b829e26b5c4642942898d9c7873cb08e048fd7deaacba8292899d5d895cb2b"
+ "digest": "7a25bbd1a7531fd34a22c654c0931d9e74bea2bbe7baa9f9cbd88f43baa79fb5"
},
{
"name": "hotel",
"unicode": "1F3E8",
- "digest": "428120a35b38a217901e10d704751eb8fdbc9f805e6eccd8aab070f4311b2085"
+ "digest": "2d78e0ad4cfb0caad778c7de49fefd6e8356afe902a43e3f1c40bceb6b0be422"
},
{
"name": "hotsprings",
"unicode": "2668",
- "digest": "df4f946218445f97a6f28c6abe4c1d1dac56ff97a8cd81df59f1b3c320e0092f"
+ "digest": "4c10c3a974b44693e8cbe91365c8b8d7f14f62db234cc516b6e54c08a6bacaed"
},
{
"name": "hourglass",
"unicode": "231B",
- "digest": "07aece9413e6898717b4f0757e073d7a593f3e8044c56855127033b796207ccb"
+ "digest": "f0bae8392aaf6f75a83f5d8914936b8650665b24ba1b232fa546b71545dd9acd"
},
{
"name": "hourglass_flowing_sand",
"unicode": "23F3",
- "digest": "92dbc68e9d16fb9f706236367e1882f0d2b6817b83ca490820a000021f2c6483"
+ "digest": "2d077729f40fc04007a933e97356bd511cbd8be76b8c55962ca3fa0d8b828e23"
},
{
"name": "house",
"unicode": "1F3E0",
- "digest": "a6221fc84a9b0e11ae71bfa1e0020982b55ff8c89a374a6d755dba710b4e058c"
+ "digest": "b4ac25979fbe161ada0d2a75769aa7552d2371d37d78cddba4ffdc7f076d3279"
},
{
"name": "house_abandoned",
"unicode": "1F3DA",
- "digest": "e404631e3a296bdeae3de7510da8934c32327bc0fa0f7ae4e676b61932165668"
+ "digest": "6e1a58533fbfe88a0eb03668c9f17c5c654a6cc7734ed798d4a885400f823610"
},
{
"name": "derelict_house_building",
"unicode": "1F3DA",
- "digest": "e404631e3a296bdeae3de7510da8934c32327bc0fa0f7ae4e676b61932165668"
+ "digest": "6e1a58533fbfe88a0eb03668c9f17c5c654a6cc7734ed798d4a885400f823610"
},
{
"name": "house_with_garden",
"unicode": "1F3E1",
- "digest": "22d0d911da96b7ae3bf6692d3cf3590afbca959fc99c13e7a088f7194f43a35d"
+ "digest": "817463f23ec0a849393ba75c333e822b4d253cd4db998c127e90d1b924f35d20"
},
{
"name": "hugging",
"unicode": "1F917",
- "digest": "68ed6c4e0eae9071cf67770a39e07a2290b4f7763170f765b3cd3ac67ae43240"
+ "digest": "69810a98b1247e1f1e496aa757e428189ef5cc086764fabd8189cf1eef82234f"
},
{
"name": "hugging_face",
"unicode": "1F917",
- "digest": "68ed6c4e0eae9071cf67770a39e07a2290b4f7763170f765b3cd3ac67ae43240"
+ "digest": "69810a98b1247e1f1e496aa757e428189ef5cc086764fabd8189cf1eef82234f"
},
{
"name": "hushed",
"unicode": "1F62F",
- "digest": "69faa8e0b170ee8cf41977ca4a5154406360ed9699d5c62ecdaa01f50e8e4276"
+ "digest": "22586107f7399eff64538a52929dade152633aa268fc5ec4e6fe1c0e00a7bd89"
},
{
"name": "ice_cream",
"unicode": "1F368",
- "digest": "d48ec98a8789148b96c30f19595201a0f85ed899659d97d1d3596091162909ff"
+ "digest": "d1a8e685f2ecf83dead28733859e369d6ce120a2669cdab97dc4423547d472ac"
},
{
"name": "ice_skate",
"unicode": "26F8",
- "digest": "6fb044d9fbe62605f6728062c35c345ddd3ae4cc51203c925b0e69f1b3ef2dbf"
+ "digest": "41ef65c143bc068868fa64080ffd447d91aa3fe2a39e69ecaa97022820af4dcd"
},
{
"name": "icecream",
"unicode": "1F366",
- "digest": "abd5774157575dd304dc1a393244757853972c863861a654ca29b2d528e48b28"
+ "digest": "22cfe17b80cbd2a0377ee90da45bd40d33533c914b2639d363fbb1f00714e194"
},
{
"name": "id",
"unicode": "1F194",
- "digest": "860ffb36d37d84e2c1cf0ab991b95c1cf73e458bef0e4d85bb0c1e26115cb2d1"
+ "digest": "bcf0922e083821d3be7951893084ea0d72a0110ef0b20d11dfec24dd70633893"
},
{
"name": "ideograph_advantage",
"unicode": "1F250",
- "digest": "37892a5642cd49ef7828646f36f48b5a83dc02437624c05da428579256118030"
+ "digest": "0b6bf59f63fda1afa92d652814a778a056c3f4abdd9cf3f6796068bd71783051"
},
{
"name": "imp",
"unicode": "1F47F",
- "digest": "f8c93d03bd9f1d5ef86738541e11695d6811bf6fef06759eba98321b6d038814"
+ "digest": "52598cf2441988f875ccb4e479637baefc679e3ca64e9a6400e56488b0fde811"
},
{
"name": "inbox_tray",
"unicode": "1F4E5",
- "digest": "066a2d75633eb50329496f6866b5b0645c2e48135a03118f1bf53244f8529043"
+ "digest": "d5d9497022b5318fcfbfdfcd56df9c65dd8f4a4cb5e6283ca260836df57da301"
},
{
"name": "incoming_envelope",
"unicode": "1F4E8",
- "digest": "ef6e5c5aa679d174181dae77113717f26e295778dde1e2c3bdf1d64de8a4af8c"
+ "digest": "310b7bdcca93452fe10c72c03d0aafa12b98e5d3408896d275d06d3693812c7a"
},
{
"name": "info",
@@ -6157,97 +6157,97 @@
{
"name": "information_desk_person",
"unicode": "1F481",
- "digest": "acae6d272e348aee87dd60360f16ac58cea7cb4e1ea962cc1655005c7f4aed27"
+ "digest": "9f12a4a58a650e8e1d3836ef857003c3ccd42ad4203a2479eb95100bf6559064"
},
{
"name": "information_desk_person_tone1",
"unicode": "1F481-1F3FB",
- "digest": "709ebb0481ca981d76ece2d4fc68db693ddf18b9c1aaa0b6ac5d3c42e71bf07f"
+ "digest": "6674f2e059eff7cfd7fd6abc800da37c4f1087feb4ff26c9e4e31aa29fdf9921"
},
{
"name": "information_desk_person_tone2",
"unicode": "1F481-1F3FC",
- "digest": "d5bc3563bc721d66b73850db93ac827be3715e7ca6420dc0051396ffe26bef47"
+ "digest": "9983412ecd130b7e9cfb078167016c06fd043b6f9f3c26d21733ca3f059fd109"
},
{
"name": "information_desk_person_tone3",
"unicode": "1F481-1F3FD",
- "digest": "af67fd4ef2fc402bec2d446b2e8ff5e9f636b5a9bbb6639587cdb88bd780d265"
+ "digest": "d8907bf47af5722127afca8fc0da587eab33044a6c60a94890983deb8d6f7a66"
},
{
"name": "information_desk_person_tone4",
"unicode": "1F481-1F3FE",
- "digest": "fd3174d1adfe13e8c0d6b6ae9c3a26ea35bb40f98f0728f91d1798809a74933b"
+ "digest": "3be086d4edfe9ca8e4a364b4e8d09b81b5b594b5eeb9ffdf6370179fb3118658"
},
{
"name": "information_desk_person_tone5",
"unicode": "1F481-1F3FF",
- "digest": "4b773c443830a02de8b4d6471077b5d1387b560b537cabba7cdc667110cbde69"
+ "digest": "2fde4e98dd11c5c29c89cad7cbb7bd2d5077dfad07913b20e01955b2d0dfad40"
},
{
"name": "information_source",
"unicode": "2139",
- "digest": "50cd8bf46d20b7c18d5f00a69fc79452aa32934245ba8d0929e51632d73876bd"
+ "digest": "b6bf3cce86d42c2e3c46470baab4af01e900b8ae337b605c3da07c3eba671269"
},
{
"name": "innocent",
"unicode": "1F607",
- "digest": "a3510fd51c17093ebe2371cfde7611aa44aed2d120a0e5500cfaae0f1d3486a4"
+ "digest": "20f8d856bc3e46f4b1173cea05d4577e1c61f06b2daba46e57db90f4066bb428"
},
{
"name": "interrobang",
"unicode": "2049",
- "digest": "1f843ff672486154f9f3df549bb1b528a5eac8d15264f447649ba57f45ee4d00"
+ "digest": "92a2d5b4c0bd6714e402f6f12fe19774cb41d081b5e9c23c415ce794224d8117"
},
{
"name": "iphone",
"unicode": "1F4F1",
- "digest": "be6f96c02ddae557f700fd20fe7b3f94c9e1c928acb82b2b8b214d231273fece"
+ "digest": "1ebc54215713cd4bf1c1e50770999f2512bb4fea29e37d0bb3a8aa2460ff875d"
},
{
"name": "island",
"unicode": "1F3DD",
- "digest": "17f02b309b62ed9542b1d8943168302846040e420f413e56d799bb5fba7064fa"
+ "digest": "7f9eb5c0cd865762f7a0f187e09c1be442de7010e7c2e113d56aae998597c90d"
},
{
"name": "desert_island",
"unicode": "1F3DD",
- "digest": "17f02b309b62ed9542b1d8943168302846040e420f413e56d799bb5fba7064fa"
+ "digest": "7f9eb5c0cd865762f7a0f187e09c1be442de7010e7c2e113d56aae998597c90d"
},
{
"name": "izakaya_lantern",
"unicode": "1F3EE",
- "digest": "ddb20f475aa119c3a64a55dff40f7a9dbc3a14f7ffc6cfbac89210c652f10d02"
+ "digest": "fbdc290e666d43d0776a73b955c26df4518692b35e72742e073705fc4ca2ae88"
},
{
"name": "jack_o_lantern",
"unicode": "1F383",
- "digest": "62a701ac472619bcb3859e0d9a61b98c7f5c32150d2d04ca8c3e8fc3bec4dbd5"
+ "digest": "78d666c2e80f64bfb6796f53e5ba4960a83ec36192110e8661031bee2b5e370a"
},
{
"name": "japan",
"unicode": "1F5FE",
- "digest": "2535300fff2b2e4b75fc73c187be6c0ea4bc4753e443db498ea55e268e627ab7"
+ "digest": "e7d9d6ebf9047fdd3c52e074ba259659c6d8e51a6abae3cdb8d6cf6dbf9a93fe"
},
{
"name": "japanese_castle",
"unicode": "1F3EF",
- "digest": "70645aa05599e23a9ac4327e4a2e78bffe7ea06c38ec1935c15ae420619c5c1c"
+ "digest": "938ae132c403330288223b88d28c19a47224d4f254fbc2366ecef73d9633112c"
},
{
"name": "japanese_goblin",
"unicode": "1F47A",
- "digest": "59b6901dc6eedc6509c25b4eef6702bf461ded06c5ff12fe2a02a5b3301577c0"
+ "digest": "63d4bcf58b9d0c29612994432aad2ae35819fdd2890674e60a2f1d51601b742e"
},
{
"name": "japanese_ogre",
"unicode": "1F479",
- "digest": "dab7e68cd4cbf99c13d64792c7104c4f0a846bc63aa12950fa8fab028dca301d"
+ "digest": "434ceedd102e7dcbc07e086811673dd63659ddf8c3ec4d029a3d759a0abfcbdb"
},
{
"name": "jeans",
"unicode": "1F456",
- "digest": "ddd032ac77cdfe49152a0e0a0eaaaea9f183590fb1f493ec30e9e39f679e3914"
+ "digest": "f986ad32e419cca81c995f8371f0189d1490172a97ebbeac60054a1af08949c5"
},
{
"name": "jet_up",
@@ -6262,37 +6262,37 @@
{
"name": "joy",
"unicode": "1F602",
- "digest": "f90cfbcb14f906f8d786b61f022c978f381fc99ca422805f605631314e101805"
+ "digest": "75d7a05043523d290c46d3b313b19ed3c95271f1110bcf234cf13d4273625b08"
},
{
"name": "joy_cat",
"unicode": "1F639",
- "digest": "6ca24a94490de66d1ca2cbc080bcd805f54ca295051d8e6588cae3fe6658c80a"
+ "digest": "a65c999604147e5e20170fcb14f80a1ff0a633f991492e1f790b2ad4caec7b7e"
},
{
"name": "joystick",
"unicode": "1F579",
- "digest": "ec172df88ef8e8a5512d6d906c13296875b7057ed0cca79f4ac8cddd9e1de34b"
+ "digest": "671ee588f397a96f27056a67e6a06d6e8d22c2109ec57b2859badb5fec9cf8dd"
},
{
"name": "kaaba",
"unicode": "1F54B",
- "digest": "30f1a27a148399bbb811586eff795eff858701c42055c23e4d5bef7ae77f5f32"
+ "digest": "a4618782f9583f077bd383965f1c91b9985a949bb7b6cec7af22914e7f5e9ab6"
},
{
"name": "key",
"unicode": "1F511",
- "digest": "c68ed648350d3976c8d27a709020c8873ecf553929e66453acff96231684a1a2"
+ "digest": "66719fa77a50a0827c8d47237e2704c03e38186e6fef80627a765473b2294c2e"
},
{
"name": "key2",
"unicode": "1F5DD",
- "digest": "87a7d42531d7a11dcb11b0d6d1be611ee8cec35b5d22226a8ac6083fedef4f5d"
+ "digest": "f57240a014a9da5da3d4d98c17d0a55e0ff2e5f2d22731d2fc867105cff54c6e"
},
{
"name": "old_key",
"unicode": "1F5DD",
- "digest": "87a7d42531d7a11dcb11b0d6d1be611ee8cec35b5d22226a8ac6083fedef4f5d"
+ "digest": "f57240a014a9da5da3d4d98c17d0a55e0ff2e5f2d22731d2fc867105cff54c6e"
},
{
"name": "keyboard",
@@ -6327,132 +6327,132 @@
{
"name": "keycap_ten",
"unicode": "1F51F",
- "digest": "7593aa7ffe7192a2e35c6ccec76522f6243777783c9152c7c03419835ea58c03"
+ "digest": "c7c9491021740d2c17edddb856f79579b0b943d8dc85a2f48dbaac84f35b8a40"
},
{
"name": "kimono",
"unicode": "1F458",
- "digest": "e92bea044fe013f1993c2229d86e9cca9d43f14aab00564ce6ff559bdc5ce93a"
+ "digest": "637182590e256c8fb74ce4c0565f5180c07f06e3bdebf30138ed3259b209c27f"
},
{
"name": "kiss",
"unicode": "1F48B",
- "digest": "c060eb09af2a0d0f77d307b995c15719b0e59c9162a490b8a553fac9b779c8f0"
+ "digest": "62f9b9ffcb01558cd5bb829344a1d1d399511663ff5235405c1f786c9416a94d"
},
{
"name": "kiss_mm",
"unicode": "1F468-2764-1F48B-1F468",
- "digest": "381364ad988ec07cc3708fd60f71838092224009088fff587069b4e8ab01ee63"
+ "digest": "6b0ae32ecb7ec0f0f43dc7a1350711185cce114c52752395f364ddbfb4f1fff4"
},
{
"name": "couplekiss_mm",
"unicode": "1F468-2764-1F48B-1F468",
- "digest": "381364ad988ec07cc3708fd60f71838092224009088fff587069b4e8ab01ee63"
+ "digest": "6b0ae32ecb7ec0f0f43dc7a1350711185cce114c52752395f364ddbfb4f1fff4"
},
{
"name": "kiss_ww",
"unicode": "1F469-2764-1F48B-1F469",
- "digest": "7705ca707b73f44c856ea324bdfe30ed05244c8d192d1111f6e1d62ab3f2f8a5"
+ "digest": "6de420cf752e706b1b7e9522b1b9be62eda069cb028c8fd587caf39f6a142e6a"
},
{
"name": "couplekiss_ww",
"unicode": "1F469-2764-1F48B-1F469",
- "digest": "7705ca707b73f44c856ea324bdfe30ed05244c8d192d1111f6e1d62ab3f2f8a5"
+ "digest": "6de420cf752e706b1b7e9522b1b9be62eda069cb028c8fd587caf39f6a142e6a"
},
{
"name": "kissing",
"unicode": "1F617",
- "digest": "3142617e8b9488689bd9efc67c0e4cc71a1870df8ffc308f949eedc5c3684051"
+ "digest": "b4a505f9e3d7fbd0ac60111f0e678cf425a5fd1abc65a3e9db59ae4abcfb8e85"
},
{
"name": "kissing_cat",
"unicode": "1F63D",
- "digest": "ed26cee8c438ba41365b55c48457cdad3e8d43bf90db3128ac5b277718b82ed3"
+ "digest": "a00431bf10601db4998e78433279167e52cbd36aed885399482529d5cdab8636"
},
{
"name": "kissing_closed_eyes",
"unicode": "1F61A",
- "digest": "22d3369d21b4c2cb4c0c2cab9551cd848dd4f9adecfa64977d3f1a80fc0c8b53"
+ "digest": "ae474db7daf80fe0b82ae1f2a11672cfcd9f9126e100f6e6d4b8a0d135dce39d"
},
{
"name": "kissing_heart",
"unicode": "1F618",
- "digest": "1f089b07447bdcc1baada6a2a9607d4ef4f2de9a6093fcab47a553a64b9acb76"
+ "digest": "bce372573bd3b347b555c1cd22087e03e650df73c8e0284ab668bf6633251632"
},
{
"name": "kissing_smiling_eyes",
"unicode": "1F619",
- "digest": "e37d282861669adfa3953b9af833acfab7d55e787621d4318d77de7e3529d5c5"
+ "digest": "f0f8636cb1a02b93cc72ce1b194b890fca823d91e35926b889be3ecfae79207f"
},
{
"name": "knife",
"unicode": "1F52A",
- "digest": "3fef068a6ada61630dc868e47d25e0e0550b44bc7cf530afe88ca63dc7ab2a39"
+ "digest": "e6189e4843c6e80875b4952fcddb0c858f7c6039b9214bbec6a261a1358425df"
},
{
"name": "koala",
"unicode": "1F428",
- "digest": "fe020ab9048f3c2a881474f8b1335db6bfaf37d115ff9b2d264f668d136122dd"
+ "digest": "c58f7e0abae42c2218a85efed0e04151df67187815bebca7f3db6f435e0dab4d"
},
{
"name": "koko",
"unicode": "1F201",
- "digest": "734a5cb296826a598e02be3f4ec22f318633ede2ce274914586256421e2df97b"
+ "digest": "5f45eb49bbf298e1fadedfe6cccc297850fcaaa4535e4cc911d48d979af55807"
},
{
"name": "label",
"unicode": "1F3F7",
- "digest": "9fe8195c3efab4d905b1cfcba0ae58cda12496030b0908de8076ff5e6777742e"
+ "digest": "9550ed50cedbc56eb1bd22a8a0809d837048a33d6e2e6e7d65c50d95fa05a85d"
},
{
"name": "large_blue_circle",
"unicode": "1F535",
- "digest": "ba4d0f84a9c2be9a65b25c8cfa78f30d4856d021b1853154dd1d2fd0c5bcfb6a"
+ "digest": "0df3fb3b09a6269459a3d9a1fe78db572190a948680844cfe758f53b6a482ff4"
},
{
"name": "large_blue_diamond",
"unicode": "1F537",
- "digest": "d5aa5e315126859c10c83507be6b9e11cbf423f7a27145de089468cff9b94a94"
+ "digest": "7f646b4e9de2788ed09e45f72cb512c269dda4989029b39bf9a2556659321651"
},
{
"name": "large_orange_diamond",
"unicode": "1F536",
- "digest": "108600badd0ef267842325c0fbf326cb3504306332c64f6f5694de2b54c9438a"
+ "digest": "80ae005ef9d79190c777f00de0993f8b3cb783f7051d76e971640c8c0827c338"
},
{
"name": "last_quarter_moon",
"unicode": "1F317",
- "digest": "68315b85bc1cb17bb82629bd1a6024a5124f3641b9878a732a8aad016c587546"
+ "digest": "3d1f276607c685d50f4b70d00a57750a57ad9ad84256dafd2dc8eef8c72300c3"
},
{
"name": "last_quarter_moon_with_face",
"unicode": "1F31C",
- "digest": "146a419109b7f662bf87cf9de299e47d025a8758c8970b7dabf3483e1956b559"
+ "digest": "d516825ba52dc67f5a01433fb9df2aa77742d38efde4225983ebc4882cbdfe5d"
},
{
"name": "laughing",
"unicode": "1F606",
- "digest": "f22d3be77f1daf058d04c3cbc1fd7f76b4dc069d2d300b45e63e768b08d269c5"
+ "digest": "e9ea994b39650740c4961f070ed492d86b3acf6e6a830a6dadaa3a6872e81b81"
},
{
"name": "satisfied",
"unicode": "1F606",
- "digest": "f22d3be77f1daf058d04c3cbc1fd7f76b4dc069d2d300b45e63e768b08d269c5"
+ "digest": "e9ea994b39650740c4961f070ed492d86b3acf6e6a830a6dadaa3a6872e81b81"
},
{
"name": "leaves",
"unicode": "1F343",
- "digest": "f65e2db125564eb04fc427a49fff175d6e2dae847bd12314d5e6a131610d5ccd"
+ "digest": "56a7a0e767a6f214d340d1b5989efd99fec52c6aa306ec5c3328e32234a1631b"
},
{
"name": "ledger",
"unicode": "1F4D2",
- "digest": "62df1772cec10c035ae0646e6cca4ba7d75b10636a520d091c5b42c2dc36b742"
+ "digest": "e58cb714353e96a2891a5d97910ff79660e637af909b81c49c919d3735db55b4"
},
{
"name": "left_luggage",
"unicode": "1F6C5",
- "digest": "62292758715115e55ab6239805b7f99b7b35bdfa8d40da07fe391424f1f083d8"
+ "digest": "6625077767a51163ea20cbc299f3c13fd5ccf1b5ce365ee702ef1fef6be3dadf"
},
{
"name": "left_receiver",
@@ -6467,107 +6467,107 @@
{
"name": "left_right_arrow",
"unicode": "2194",
- "digest": "28a6945972451b1f4dadec5c55310b8868ffd9f3b0a07803287bc4e07a56e7d4"
+ "digest": "560fcf1b794eb0d5269c73b3f8da57540cbb8a6f1a9af7a9d10b202252247e34"
},
{
"name": "leftwards_arrow_with_hook",
"unicode": "21A9",
- "digest": "d672afc39fd50f78d7370be243173fe76ba50292f0c401305b562898939a8b7f"
+ "digest": "504714c5559b1bd35aa469be83069a923d1a25f364cac08c10df0195749e7b26"
},
{
"name": "lemon",
"unicode": "1F34B",
- "digest": "e0e293a8b8c1b3c87534f5e05cf006671eb3c6d52b4d17d40f2e23bce215a8be"
+ "digest": "ccca25bb6ac47770dba3aaf75144128f9a73299061969b25a35ad1733dcde5fe"
},
{
"name": "leo",
"unicode": "264C",
- "digest": "b0fd4e5f4637de530b62323521c6edcd80312d67ea4043eedd959acb6763474a"
+ "digest": "f2ed930e279699962f189e0cac519cc29d339b3e82debfdc90c5b0935a7543bb"
},
{
"name": "leopard",
"unicode": "1F406",
- "digest": "ede891be8484a17e6277431c64ec1bfd6b742544a41947ebc85005bc2d558bb1"
+ "digest": "d4a8964b6f2cdf6ddf074d0f1f2f65783a1a43eb4af426905fad0e60899939c7"
},
{
"name": "level_slider",
"unicode": "1F39A",
- "digest": "49777cf160d9130d723e3bfef765c3de54033e6b059000fb0e22fb559b5ed190"
+ "digest": "48842324f54d971ebf548a89a82ac7f29e235702081c91b477b1a92d427290e7"
},
{
"name": "levitate",
"unicode": "1F574",
- "digest": "3e4e9a5ac6a8dbd7909c58a9d915f16f1a0fc59cc019714ae5935f18e4704044"
+ "digest": "453c24bf2544ed3ef3c710a7fabbd5fdace4dc65cddd377274d30d921523b50b"
},
{
"name": "man_in_business_suit_levitating",
"unicode": "1F574",
- "digest": "3e4e9a5ac6a8dbd7909c58a9d915f16f1a0fc59cc019714ae5935f18e4704044"
+ "digest": "453c24bf2544ed3ef3c710a7fabbd5fdace4dc65cddd377274d30d921523b50b"
},
{
"name": "libra",
"unicode": "264E",
- "digest": "ec8e2e7a735abc9f2bddb115fc0e09f4bdc7a164679e2b57d127f58eee1155c2"
+ "digest": "e330ba05bb449db074bc23d1514246ca5e249110f44ddb5804e5510eef6deac1"
},
{
"name": "lifter",
"unicode": "1F3CB",
- "digest": "f64db037fd21e5918e5de35d6a561ef4b44668e307ed351338de00fcf3e771e3"
+ "digest": "d6c94a32eb863d14a2a01add8ab95040f42a55d9e3f90641a0fe143d58127558"
},
{
"name": "weight_lifter",
"unicode": "1F3CB",
- "digest": "f64db037fd21e5918e5de35d6a561ef4b44668e307ed351338de00fcf3e771e3"
+ "digest": "d6c94a32eb863d14a2a01add8ab95040f42a55d9e3f90641a0fe143d58127558"
},
{
"name": "lifter_tone1",
"unicode": "1F3CB-1F3FB",
- "digest": "f9e0d161b12c4908ac3409b11c1a77ee38f33ba018f12416545876214bfb7c01"
+ "digest": "870acf2f554fce360b58d3e98b4c0558d7ec7775587776c0f9d40c6fb1bdacf9"
},
{
"name": "weight_lifter_tone1",
"unicode": "1F3CB-1F3FB",
- "digest": "f9e0d161b12c4908ac3409b11c1a77ee38f33ba018f12416545876214bfb7c01"
+ "digest": "870acf2f554fce360b58d3e98b4c0558d7ec7775587776c0f9d40c6fb1bdacf9"
},
{
"name": "lifter_tone2",
"unicode": "1F3CB-1F3FC",
- "digest": "631eb6ed5bd147dc6f1f8b94149abe44d62a0f78e7809e37a4bfe127c40ed98f"
+ "digest": "1a7ece8512e42241cdd95c85ccc509bc0ff9c7c6ffaff2be343c77f417a27576"
},
{
"name": "weight_lifter_tone2",
"unicode": "1F3CB-1F3FC",
- "digest": "631eb6ed5bd147dc6f1f8b94149abe44d62a0f78e7809e37a4bfe127c40ed98f"
+ "digest": "1a7ece8512e42241cdd95c85ccc509bc0ff9c7c6ffaff2be343c77f417a27576"
},
{
"name": "lifter_tone3",
"unicode": "1F3CB-1F3FD",
- "digest": "406b5707a47d9066f016acf0b64fa695e3505acc2453758a0428de21efd7eb6d"
+ "digest": "4bc633ee82a0fb59feba379fb6901a489e4ac849d758f9c8e7a1a0a26eaa380c"
},
{
"name": "weight_lifter_tone3",
"unicode": "1F3CB-1F3FD",
- "digest": "406b5707a47d9066f016acf0b64fa695e3505acc2453758a0428de21efd7eb6d"
+ "digest": "4bc633ee82a0fb59feba379fb6901a489e4ac849d758f9c8e7a1a0a26eaa380c"
},
{
"name": "lifter_tone4",
"unicode": "1F3CB-1F3FE",
- "digest": "d917164ed8c4bb1ffcc887ca256ec329e7fa1b9516eaf8c159f8b43fdb071ed6"
+ "digest": "d086fe5577b5ba80676f2224d886f8ebe4588314f429f12a34c52c971ed71b5c"
},
{
"name": "weight_lifter_tone4",
"unicode": "1F3CB-1F3FE",
- "digest": "d917164ed8c4bb1ffcc887ca256ec329e7fa1b9516eaf8c159f8b43fdb071ed6"
+ "digest": "d086fe5577b5ba80676f2224d886f8ebe4588314f429f12a34c52c971ed71b5c"
},
{
"name": "lifter_tone5",
"unicode": "1F3CB-1F3FF",
- "digest": "f79ea93e8a40b3c895b693bf49eb4ce6e7b3f4413595e5881ea44839fd7fe8e5"
+ "digest": "79b0edf6ce1fd024dd7f458e322ad8588af0b789a04cc1cf38380dc8b9c76f55"
},
{
"name": "weight_lifter_tone5",
"unicode": "1F3CB-1F3FF",
- "digest": "f79ea93e8a40b3c895b693bf49eb4ce6e7b3f4413595e5881ea44839fd7fe8e5"
+ "digest": "79b0edf6ce1fd024dd7f458e322ad8588af0b789a04cc1cf38380dc8b9c76f55"
},
{
"name": "light_check_mark",
@@ -6582,27 +6582,27 @@
{
"name": "light_rail",
"unicode": "1F688",
- "digest": "7c2be55456f1332e849ff6699a26dda2e1641c280f45c9ec88dedf6d9b7b7fe2"
+ "digest": "2f30b23a738371690b2f00d96ddb5ceb90a1442b5478754626a3dfa263ed2fc1"
},
{
"name": "link",
"unicode": "1F517",
- "digest": "cc4873f8a612dd721dddcd507a4430b4fb6c4abc15a8848456f0ffd97811b163"
+ "digest": "7bf567aabd1fc38b3d70422f9db3a13b50950cf6207e70962c9938827c196ccb"
},
{
"name": "lion_face",
"unicode": "1F981",
- "digest": "935b1076815f51fafcd860a395d0a03c536acfcea61ffcf542a377da046fa7d9"
+ "digest": "dd24f2668e973ec973e97dc111f59a2cc14e9b608387401191dd53368d28d4fa"
},
{
"name": "lion",
"unicode": "1F981",
- "digest": "935b1076815f51fafcd860a395d0a03c536acfcea61ffcf542a377da046fa7d9"
+ "digest": "dd24f2668e973ec973e97dc111f59a2cc14e9b608387401191dd53368d28d4fa"
},
{
"name": "lips",
"unicode": "1F444",
- "digest": "e3bc20f9e210fa1711271234fe61bf1c9ddf36dd6ffc5b832c6c3a769a1e59a8"
+ "digest": "8740d8086525c7a836d64625a6915cc1c59af69ba143456dbb59e0179276895e"
},
{
"name": "lips2",
@@ -6612,477 +6612,477 @@
{
"name": "lipstick",
"unicode": "1F484",
- "digest": "335b912e163020df3d6d9f0a19a55d6547bd59b471c5a3e374c2968e49911ccc"
+ "digest": "751dcb22706a796033b13a2ccb94304236ec13207ad4d011e02d230ae33ab5c1"
},
{
"name": "lock",
"unicode": "1F512",
- "digest": "c20eacfb8ccd9bb85919a837c0d4650ee608edb48c85bff46945f613e95d7038"
+ "digest": "043b4fc0b8c79d47a07d91308e628e1ac262aea6c1ec05e6b84bf7bcdf89dc83"
},
{
"name": "lock_with_ink_pen",
"unicode": "1F50F",
- "digest": "5cab25cea08e22d9c3f5de16de6d0ab658ca15cc93d7830f29b0f3e9348ec45f"
+ "digest": "7b5e959b26cf7296c7b230fc2be9feb9e38391c5001951a019d16b169a71aba9"
},
{
"name": "lollipop",
"unicode": "1F36D",
- "digest": "33d2334a00bf0e15869ccc75fadc36f27f89abf0525bb71f859aad9e1dc4ad66"
+ "digest": "17b6a0df47ec758a2f9c087b46a6902cee344d39407ef4c321e408505cbb72ca"
},
{
"name": "loop",
"unicode": "27BF",
- "digest": "fa1174ddc44e317d0796e07868c7ac8ac9c9274fbc8a6c3d0ec78d543c3c6bf0"
+ "digest": "9f20ecc34b3c871789ba7d0712aa31e7a74b6c1558ac8bea385bc40590056726"
},
{
"name": "loud_sound",
"unicode": "1F50A",
- "digest": "fb70229e13b690ffc1031d2e631123f8c908035a15218c297c1c4a3ff3624aa0"
+ "digest": "64b12db9ddd8adf74a9fc2bd83c7979ea865113347f7ce8666e9ccf5019e715f"
},
{
"name": "loudspeaker",
"unicode": "1F4E2",
- "digest": "e2d6cf9ec6412ee62f3128a1afd8c63ec74755c4833f01a4f99722407fe154d6"
+ "digest": "1e1f35d16dd2898ebaa6f2b2868203df6e09c8a70df069c92d6d1b5cb2ac0976"
},
{
"name": "love_hotel",
"unicode": "1F3E9",
- "digest": "184670ebc4045043a7b18d576da3255d216551da522a11cde7df34524e9c7d50"
+ "digest": "ff8966a50fd47a216855488eb09a367d231fea21f49e7e5325191d32fb494473"
},
{
"name": "love_letter",
"unicode": "1F48C",
- "digest": "9a4c52e2622fc7d364995ebc93ca530d972134621d117b72053a659dffc90ffc"
+ "digest": "037261c8ca4d72f7205e51664591696da2ae7ceb19f1c1c9f6123da5a5979d29"
},
{
"name": "low_brightness",
"unicode": "1F505",
- "digest": "c177b7fa9fdbef959cc47e7d16becd71117470b767a81ed6d15f80f464776c02"
+ "digest": "a065d00a416e297c168b0a675cafcf492fedf94865cb21801a1be5a3914593d4"
},
{
"name": "m",
"unicode": "24C2",
- "digest": "2eaf011e74d69613923dad424daaec4c13b592388dbcc5757b645bc058eedecb"
+ "digest": "54588ac2b7fcd53a96f17124e9de69b617613fcd5af9ad2930a094cb795bb9f4"
},
{
"name": "mag",
"unicode": "1F50D",
- "digest": "029427bd73d2c79fffc5194ded01f6011952ec0124b7634c6230e0afa7ad7c95"
+ "digest": "a6e31a2efa7d9427aaa30b45d9f4181ee55c44be08aea2df165a86e0e6d9eaa1"
},
{
"name": "mag_right",
"unicode": "1F50E",
- "digest": "f99de50bb59ec3bf1d4ccb8584ca09d4a7ceb5bf9f600ea8d3f84930efbf01b8"
+ "digest": "c7d8ceeb05db261e5eaab31dc4da432d0d5592a2ed71e526c5a542daa230bbaf"
},
{
"name": "mahjong",
"unicode": "1F004",
- "digest": "da5d1fa980c38e092d414516161ca26046aa65ace3261999ea750f72e676ac6e"
+ "digest": "755d69f988434ce1c17531a8b7ac92ead6f5607c2635a22f10e0ad70f09fc3e6"
},
{
"name": "mailbox",
"unicode": "1F4EB",
- "digest": "14217df8f39a95fc0a0c527f97db1ca8564764034e921614decc5be705629352"
+ "digest": "2069091be90a530a43ef29d5ec7688c351bf4d5b08d63a0d20d72b67d639ec62"
},
{
"name": "mailbox_closed",
"unicode": "1F4EA",
- "digest": "e0c7beb205ec548a66d8afc7f103b64c6c79c08417ab550f19c36cc6d1a62bc4"
+ "digest": "d88d65bfebb8216535fd055c69f319564b2cf0b0901820f8312f581864557ed4"
},
{
"name": "mailbox_with_mail",
"unicode": "1F4EC",
- "digest": "6d381c0c4181be628d9409df1d85f8a9438c21ef5b92d82ef8ae1ff0079236de"
+ "digest": "69e966b4659128991a70c6a2dd4d647551bedb91bdf5ce688958686bbec56381"
},
{
"name": "mailbox_with_no_mail",
"unicode": "1F4ED",
- "digest": "74843d5ea9e03b48323f2252bdd000585f549b7fffe1fe181a25c38b99b5e23d"
+ "digest": "9e92d8ee88f660ce56da61077c80ec26c5d8f54ebd2306c4cfa16f6c1b981f83"
},
{
"name": "man",
"unicode": "1F468",
- "digest": "0275935258b4c832c3fcb06531d3e6972e2c3d46bab2973004750a9f00bd4cb6"
+ "digest": "42b882d2c6aa095f1afcf901203838d95c1908bdc725519779186b9c33c728d7"
},
{
"name": "man_tone1",
"unicode": "1F468-1F3FB",
- "digest": "1f6603d040f4a025f49d384170dd16b8da169663fc3282af1dc8710d9c1a7adf"
+ "digest": "7053e265fa7d2594de54a6c5d06c21795b9a7dfb36a1c5594ca43c4c6cc56504"
},
{
"name": "man_tone2",
"unicode": "1F468-1F3FC",
- "digest": "d65bb03071b483946c69c61769d19b29a2af76fa7e43020e55f0bbc046492221"
+ "digest": "7ebc64de40d3ac60fb761be5cf94f53fa10b4f03fb66add46c90f5d98eaf71eb"
},
{
"name": "man_tone3",
"unicode": "1F468-1F3FD",
- "digest": "9af8ede7211b19a7dc0c60db083dd2bdc4897dda4d71e57feadf2e39d847f060"
+ "digest": "77ceef4d3740ed4751acb83dd45b6b754cf625c522c6757309cd4d61202d7149"
},
{
"name": "man_tone4",
"unicode": "1F468-1F3FE",
- "digest": "6555de60976aafeb024db78addb44eab2a412dd7277013f44d06757d03b6a252"
+ "digest": "41e6037c393f61cca61b9a81b27ed14a95d75fe380e3a00153c33a371a836ffd"
},
{
"name": "man_tone5",
"unicode": "1F468-1F3FF",
- "digest": "b58b97a28a6adc1777acc05194cd917c730f90e37441124c384ded12e9a7d2a4"
+ "digest": "a8cebfd39a5b9c79af7cc37f205e1135376056fee287af967c9f55d415572d99"
},
{
"name": "man_with_gua_pi_mao",
"unicode": "1F472",
- "digest": "88663173a6ccbebec5e24883c90d965447e022c6688773273110fe544d5b1607"
+ "digest": "3dae285e900c69986a48db0fa89d4f371a49f38608059cdae52be098030c5ac4"
},
{
"name": "man_with_gua_pi_mao_tone1",
"unicode": "1F472-1F3FB",
- "digest": "3c8bad3923a619f888e14544d357499a26a517e8fbe7a51027117b960c9eb842"
+ "digest": "35404d8e266920c78edd9e7143fb052b42f65242a5698494c4f4365e9183cc67"
},
{
"name": "man_with_gua_pi_mao_tone2",
"unicode": "1F472-1F3FC",
- "digest": "da125a3310fab19c9282497d53e2fc71ad07920ce60a0ef52dcdb31500023f09"
+ "digest": "82d4f968665a93c7543372c8a1eeb0f25d0ea6842d5e518bd91c226c6c3ab8c2"
},
{
"name": "man_with_gua_pi_mao_tone3",
"unicode": "1F472-1F3FD",
- "digest": "1d5842558847367966bf3ea473ff80fe744359bc5d969f4cc06cf2e452ed2fb6"
+ "digest": "f44159f0c672b9b833449382896180e799abf574f5b3c6cd9541caa992fa18ce"
},
{
"name": "man_with_gua_pi_mao_tone4",
"unicode": "1F472-1F3FE",
- "digest": "92be490f3ba602a43e2be8160d8bfd8a0691b2f81fe017b06df10f476a89ffab"
+ "digest": "c79060188f9461ca34eaa225b7682d8c410883609509fb731c992db69bfeeb50"
},
{
"name": "man_with_gua_pi_mao_tone5",
"unicode": "1F472-1F3FF",
- "digest": "669f6b31bc7a8bf50b169d0600f14e00addaeb24144a1bace8b94950372839b0"
+ "digest": "de9e4acdb10f7abddeeabc0b48d91139fc8b544a601c530db811f099991b0d38"
},
{
"name": "man_with_turban",
"unicode": "1F473",
- "digest": "87d30d35ba40ee39c2df8ce19d975ce34a9c54688bafeac7377d7d481e55f1a4"
+ "digest": "db72c944e93983f38d00e3e936ebb5b243c6069f1f1236d46f6a9f1beb8d6634"
},
{
"name": "man_with_turban_tone1",
"unicode": "1F473-1F3FB",
- "digest": "33b8b8154e0691e2ad66177dbf1e0101411fd8b3a16bf4e54c36d4a874f2a275"
+ "digest": "b6d7489c4cd151af09fff48b62c54c336303e14866e6ef38f94cd834b085d09e"
},
{
"name": "man_with_turban_tone2",
"unicode": "1F473-1F3FC",
- "digest": "1a6b83faa8d6e6a7d12a04898a6f22243287330a1faa081d2626b17dfb07174d"
+ "digest": "7854ef973c21847f452d7e78e5c460ea300e12b539ce92c69dabe8f1bf3a4382"
},
{
"name": "man_with_turban_tone3",
"unicode": "1F473-1F3FD",
- "digest": "5d43da5109e688ff8ca0675f33ebbaf930e206f1f01e3ee773f2844663fe572b"
+ "digest": "1dbd9bd78f5263cbadee7d0d5754c14cfbc914f7329e25fbd97d9f5b8ce0737e"
},
{
"name": "man_with_turban_tone4",
"unicode": "1F473-1F3FE",
- "digest": "bfaf7293c5ea75d0ecdc6fe5afe8f48e7b29b2e0df06ef974d3e1732f5db5dd4"
+ "digest": "4f4804da4a7c98ad4f9db3ae3eaf674c8977c638e73414e33ef1f65098e413a3"
},
{
"name": "man_with_turban_tone5",
"unicode": "1F473-1F3FF",
- "digest": "fba2404dd3d7eab5268519894cc0b386e1b17fdf14a04760c346014aa0e25acd"
+ "digest": "240282aa346ef9b1d0d475ea93a02597697f0f56f086305879b532b0b933210a"
},
{
"name": "mans_shoe",
"unicode": "1F45E",
- "digest": "45dc13ac44c922b4c4b8ecb2e1a870a78e09d53da86843431ab0e9ec96ebcd97"
+ "digest": "f53fe74abd9906cd3e2dd7e7bddbe1feb9f8f7be28b807fabe452f1f60ca1b84"
},
{
"name": "map",
"unicode": "1F5FA",
- "digest": "f56116d09996d6d08fb5cdfb46622b545253f2649008170fc2011a9713fa875b"
+ "digest": "84f496a062b5c3ae1e8013506175a69036038c8130891bcf780a69ce7fcbe4de"
},
{
"name": "world_map",
"unicode": "1F5FA",
- "digest": "f56116d09996d6d08fb5cdfb46622b545253f2649008170fc2011a9713fa875b"
+ "digest": "84f496a062b5c3ae1e8013506175a69036038c8130891bcf780a69ce7fcbe4de"
},
{
"name": "maple_leaf",
"unicode": "1F341",
- "digest": "40c5ee93396301911391cf6e70454b6fa8020fe5c85d3364136bcedb5d052cdb"
+ "digest": "72629a205e33f89337815ad7e51bb5c73947d1a9f98afe5072bdf4846827ae72"
},
{
"name": "mask",
"unicode": "1F637",
- "digest": "e0301cd27eb8c74c9772ff05b880215fc031ac1ae7f3177cd24ba0acb43b3834"
+ "digest": "1b58af9ae599308aabf41bbd38f599fa896bd9fe5df7a40be9f2dc7e0e230600"
},
{
"name": "massage",
"unicode": "1F486",
- "digest": "856d0fb1144ee91c58dfad74f9a2cababf6bae4b3ceba2a95c03ecd44ae3aa21"
+ "digest": "6ee48b4d8cec0bf31e11d7803ad9fc1f909457c8c00cb320b5671395af3c170c"
},
{
"name": "massage_tone1",
"unicode": "1F486-1F3FB",
- "digest": "fd53b06eb0967303c0914ebb79fd872900ec0f71b2852c7238517e192e5023e1"
+ "digest": "9da162c2f39628156b87db986a6ada59372a9e9a6b3f0488d21c9e65ec3309bb"
},
{
"name": "massage_tone2",
"unicode": "1F486-1F3FC",
- "digest": "7ef57359a339ae1ca4488f9a6195a352e74daf5b67d8e1ae1e91fe866921c40c"
+ "digest": "ac259188549b5b429b8c4929e1da2314859e8857ee49720551467aedfcc96567"
},
{
"name": "massage_tone3",
"unicode": "1F486-1F3FD",
- "digest": "e4fb643b6242bedb395e503ae337a88b2a255b5fda88b4aaa93396f948614a6e"
+ "digest": "cfd9c105b6debc10448f172afcb20d4192899f7ae5aa8af54c834153a5466364"
},
{
"name": "massage_tone4",
"unicode": "1F486-1F3FE",
- "digest": "94f007c2daf9455fa8d2b10cc7ccff7db9bc9daf835ef5c3699be091938db833"
+ "digest": "38ab715c621c58454f3cb09153a96380118cf082568554b6edc5f83fb62e9297"
},
{
"name": "massage_tone5",
"unicode": "1F486-1F3FF",
- "digest": "d18e800b728bf45b500f492062dc81312ca1ad7b1a0277a3d5bc150e4632ea1c"
+ "digest": "32480457734121b0c83e9be6d693ae379c95535f43f963c0c2f0f20434ee12c6"
},
{
"name": "meat_on_bone",
"unicode": "1F356",
- "digest": "674a2a58e174b7681eef3b6c5b39c098ed9374cc610d037166c0092ee5269a97"
+ "digest": "d71a8e0b118d5e6ca60690793ce9649afb78e707fcbd7be890a75564c94434fd"
},
{
"name": "medal",
"unicode": "1F3C5",
- "digest": "270d438b6e2155e944dc734ea3e4d02409e51f59db2db636398fbf96e5edb0e6"
+ "digest": "9600cbe57e08da090c60629bcafd2821c87322e738c2454f8e883ceb756e7391"
},
{
"name": "sports_medal",
"unicode": "1F3C5",
- "digest": "270d438b6e2155e944dc734ea3e4d02409e51f59db2db636398fbf96e5edb0e6"
+ "digest": "9600cbe57e08da090c60629bcafd2821c87322e738c2454f8e883ceb756e7391"
},
{
"name": "mega",
"unicode": "1F4E3",
- "digest": "540ab4fd5bab041a681749b85e6de598ebcbfc4fbf5c3cdbd9ca1e8256191733"
+ "digest": "4b1def6b5b051c5045514063f0ac006222ad81fbfe56d840e14bb950713e331b"
},
{
"name": "melon",
"unicode": "1F348",
- "digest": "39dd0ecb23e2d3da6cbb7309333fed5d7e2cb38c0afc526ade78520eca11b5f4"
+ "digest": "0cdd663e6f2129808856cdf0746e6571b62aac641f224adb553baf3bb63ba3bd"
},
{
"name": "menorah",
"unicode": "1F54E",
- "digest": "5f81bc2e5a34bf76481d2958fdb0b4e4540c599aa837a6453609a39023885d8c"
+ "digest": "49fca8c3bc00ea69653ee2f8d4e21e561856ba39716c13e9d107db3e805a2997"
},
{
"name": "mens",
"unicode": "1F6B9",
- "digest": "5ed56cff80e8ee7ed581f2a2e365915db5cb29df89e850e0add0b68db4b0c788"
+ "digest": "7d92292586ee12a5d1a557c37da4d14708dc3ce701cf32d3280dcc83d91e5df8"
},
{
"name": "metal",
"unicode": "1F918",
- "digest": "45e5fac0b9b019cf217dcfd1380cafb0d03063454612178278dac1ca5f8476a6"
+ "digest": "ffb750caf187f5d821c990108e2699ac3e216492bcff6ee543f4a7aa55b9fd29"
},
{
"name": "sign_of_the_horns",
"unicode": "1F918",
- "digest": "45e5fac0b9b019cf217dcfd1380cafb0d03063454612178278dac1ca5f8476a6"
+ "digest": "ffb750caf187f5d821c990108e2699ac3e216492bcff6ee543f4a7aa55b9fd29"
},
{
"name": "metal_tone1",
"unicode": "1F918-1F3FB",
- "digest": "9b3596fe7c063df838f0a43fb680ce10fb88e2b73c5c3324abfa357a224c17aa"
+ "digest": "5505f0b0340f9ba572db8897e40adf598cfa784686ad5ee360a7351bf44ddc1d"
},
{
"name": "sign_of_the_horns_tone1",
"unicode": "1F918-1F3FB",
- "digest": "9b3596fe7c063df838f0a43fb680ce10fb88e2b73c5c3324abfa357a224c17aa"
+ "digest": "5505f0b0340f9ba572db8897e40adf598cfa784686ad5ee360a7351bf44ddc1d"
},
{
"name": "metal_tone2",
"unicode": "1F918-1F3FC",
- "digest": "e15a4898a0efca4354ac48d6b01ff0618ce8b110b1246a4f5d78e19b54658be6"
+ "digest": "8f9eee3ad5fc7eeeb30118d16d27467b16fd87297e0ecf02656db77e701f5aeb"
},
{
"name": "sign_of_the_horns_tone2",
"unicode": "1F918-1F3FC",
- "digest": "e15a4898a0efca4354ac48d6b01ff0618ce8b110b1246a4f5d78e19b54658be6"
+ "digest": "8f9eee3ad5fc7eeeb30118d16d27467b16fd87297e0ecf02656db77e701f5aeb"
},
{
"name": "metal_tone3",
"unicode": "1F918-1F3FD",
- "digest": "c159e8179cb1907c246b432d87c5253b914fd7cebb6ac05292c4e38eff4815b0"
+ "digest": "8270a7ecf5eb11431a07ef04cc476c2651ac8aacb0d4768e5cb69355f8a5e84e"
},
{
"name": "sign_of_the_horns_tone3",
"unicode": "1F918-1F3FD",
- "digest": "c159e8179cb1907c246b432d87c5253b914fd7cebb6ac05292c4e38eff4815b0"
+ "digest": "8270a7ecf5eb11431a07ef04cc476c2651ac8aacb0d4768e5cb69355f8a5e84e"
},
{
"name": "metal_tone4",
"unicode": "1F918-1F3FE",
- "digest": "a8a43a88028c97074321e3da56df1045db41ede58bf286c21d7ae90f222f2011"
+ "digest": "f24f7b137dd6c7899dc0a8794204bbde7ad43ec1e63b419c90dd70a8b77871e8"
},
{
"name": "sign_of_the_horns_tone4",
"unicode": "1F918-1F3FE",
- "digest": "a8a43a88028c97074321e3da56df1045db41ede58bf286c21d7ae90f222f2011"
+ "digest": "f24f7b137dd6c7899dc0a8794204bbde7ad43ec1e63b419c90dd70a8b77871e8"
},
{
"name": "metal_tone5",
"unicode": "1F918-1F3FF",
- "digest": "e6611e826e867e2c73a8cadb138e4aa6365e3583dd229ff24b3e8f161904bf56"
+ "digest": "07b0726a632653b980df775f460cd3fe1ea8d4a7b0b46fe29e089b66579482d2"
},
{
"name": "sign_of_the_horns_tone5",
"unicode": "1F918-1F3FF",
- "digest": "e6611e826e867e2c73a8cadb138e4aa6365e3583dd229ff24b3e8f161904bf56"
+ "digest": "07b0726a632653b980df775f460cd3fe1ea8d4a7b0b46fe29e089b66579482d2"
},
{
"name": "metro",
"unicode": "1F687",
- "digest": "532378cf385f9a7fafe2f5c8203e675be6d38798871f4c8e2c50498a1529f956"
+ "digest": "b380247b61b5e2ca1b9b70fabff65907b2c3a5191a14b169ae094af94659b9b1"
},
{
"name": "microphone",
"unicode": "1F3A4",
- "digest": "46da2b94e4dc233f640249103f09ec915aaa812cce90afe68fedb6774a27ad4b"
+ "digest": "9ef4fc2e40d5391c4bb2d30f34f59662cff7cbb1b04341c9dac210d0e21b44ae"
},
{
"name": "microphone2",
"unicode": "1F399",
- "digest": "f9df32cd207808f67a895d3460a215d1ecc42e377907bcd64731c02b697d4f32"
+ "digest": "8a30464d51f7f101335778444c43270ac0679900f49463e6556682d9db1cb4dc"
},
{
"name": "studio_microphone",
"unicode": "1F399",
- "digest": "f9df32cd207808f67a895d3460a215d1ecc42e377907bcd64731c02b697d4f32"
+ "digest": "8a30464d51f7f101335778444c43270ac0679900f49463e6556682d9db1cb4dc"
},
{
"name": "microscope",
"unicode": "1F52C",
- "digest": "79918f5fe0a39f31f270a481f4c6e00ea49fc09d64b1ae78770971293c2b1ed8"
+ "digest": "4ca4322c6ba99b8c15acdb8b605f84f87398769e504b262b134c1f3868b2692f"
},
{
"name": "middle_finger",
"unicode": "1F595",
- "digest": "c6320b236a4a9593aeade511b52dd3114207e947458cb3b818c78737a505fdf6"
+ "digest": "0c3f1cc0ec7323f6d19508ad22fa90050845f7b5cc83f599ab2cacb89cf5dd0e"
},
{
"name": "reversed_hand_with_middle_finger_extended",
"unicode": "1F595",
- "digest": "c6320b236a4a9593aeade511b52dd3114207e947458cb3b818c78737a505fdf6"
+ "digest": "0c3f1cc0ec7323f6d19508ad22fa90050845f7b5cc83f599ab2cacb89cf5dd0e"
},
{
"name": "middle_finger_tone1",
"unicode": "1F595-1F3FB",
- "digest": "93c7aa994856185519d576cb779bdcff3a33f7077eef98e70968125f92f02448"
+ "digest": "4ebecf1058a3059aaa826eaad39c1a791120f115f65dde6d6ae32fc5561f60f7"
},
{
"name": "reversed_hand_with_middle_finger_extended_tone1",
"unicode": "1F595-1F3FB",
- "digest": "93c7aa994856185519d576cb779bdcff3a33f7077eef98e70968125f92f02448"
+ "digest": "4ebecf1058a3059aaa826eaad39c1a791120f115f65dde6d6ae32fc5561f60f7"
},
{
"name": "middle_finger_tone2",
"unicode": "1F595-1F3FC",
- "digest": "a0de802294717b80e08d9d30f5fd64eacb90b5b3b9d7a0c27d6226a22822597f"
+ "digest": "85ff506a08c38663c2dfa2e3a90584c02a36aa3dda33af47cdb49834bf9baf83"
},
{
"name": "reversed_hand_with_middle_finger_extended_tone2",
"unicode": "1F595-1F3FC",
- "digest": "a0de802294717b80e08d9d30f5fd64eacb90b5b3b9d7a0c27d6226a22822597f"
+ "digest": "85ff506a08c38663c2dfa2e3a90584c02a36aa3dda33af47cdb49834bf9baf83"
},
{
"name": "middle_finger_tone3",
"unicode": "1F595-1F3FD",
- "digest": "8bbbab07c838257416bbf8377904362c07019fca9d5abf9fd048ccf6370178da"
+ "digest": "cac697ff5207bf8a4e091912f3127f4e73c88ef69b5c6561d1d7b12ed60be8f1"
},
{
"name": "reversed_hand_with_middle_finger_extended_tone3",
"unicode": "1F595-1F3FD",
- "digest": "8bbbab07c838257416bbf8377904362c07019fca9d5abf9fd048ccf6370178da"
+ "digest": "cac697ff5207bf8a4e091912f3127f4e73c88ef69b5c6561d1d7b12ed60be8f1"
},
{
"name": "middle_finger_tone4",
"unicode": "1F595-1F3FE",
- "digest": "d9eed8db540fdb669c6ae5ef168b77659660589f5ddd9b66062274d335a3ef04"
+ "digest": "9324a5a4e3986b798ad8c61f31c18fb507ca7a4abfd6e9ae1408b80b185bf8c7"
},
{
"name": "reversed_hand_with_middle_finger_extended_tone4",
"unicode": "1F595-1F3FE",
- "digest": "d9eed8db540fdb669c6ae5ef168b77659660589f5ddd9b66062274d335a3ef04"
+ "digest": "9324a5a4e3986b798ad8c61f31c18fb507ca7a4abfd6e9ae1408b80b185bf8c7"
},
{
"name": "middle_finger_tone5",
"unicode": "1F595-1F3FF",
- "digest": "0519c3298040e57db202294476df239edb9b23b44848bab296bc45eda7cf8664"
+ "digest": "078f917cd4d8be08a880724e9400449980d92740ccbee4a57f5046a9cf7f6575"
},
{
"name": "reversed_hand_with_middle_finger_extended_tone5",
"unicode": "1F595-1F3FF",
- "digest": "0519c3298040e57db202294476df239edb9b23b44848bab296bc45eda7cf8664"
+ "digest": "078f917cd4d8be08a880724e9400449980d92740ccbee4a57f5046a9cf7f6575"
},
{
"name": "military_medal",
"unicode": "1F396",
- "digest": "bd1da0004768f404c6bb4db85d4b748f766a77ab3edb74e709d0c0064509a043"
+ "digest": "5da18351dc14b66cfc070148c83b7c8e67e6b1e3f515ae501133c38ee5c28d3d"
},
{
"name": "milky_way",
"unicode": "1F30C",
- "digest": "598b4e641c1081bb03ce38a29f9711fc8616373216a833e4daa14fbe97a358f5"
+ "digest": "17405ff31d94b13a1fb0adcda204b8adb95ca340bc3980d9ad9f42ba1e366e7d"
},
{
"name": "minibus",
"unicode": "1F690",
- "digest": "3d15791ca96349c3abb5bd5d1014b6b33b984db19609f56f5fd1e8d2fc551809"
+ "digest": "08ccb4b1bf397b7c9aed901e2b5dcdd6cb8ca5c5487ef26775bb3120f7b92524"
},
{
"name": "minidisc",
"unicode": "1F4BD",
- "digest": "83c4bfda4e0a80785fa1c3f2bbf3c15aca2bda8ea3727ce78bc4236e1e377a36"
+ "digest": "bebf82c0b91ef66321e7ae7a0abf322e59b2f7d8e6fbf9a94243210c00229c59"
},
{
"name": "mobile_phone_off",
"unicode": "1F4F4",
- "digest": "cfe6dfd766b9e0b4768df25d6e943c9abc0e910ff5e5c7a8a0f425c786bbab8d"
+ "digest": "6f9d8d6a32fc998f5d8144a5ff7e2ad00de37ad464cd97285e7c72efb09a1feb"
},
{
"name": "money_mouth",
"unicode": "1F911",
- "digest": "3ac2f9b5409e1426eef6966938ca04cf78aeffefd43f44b6c86af4af7836e22f"
+ "digest": "5a43973dadf48a89201b1816fea9972c5cfe501a26fe457b6f7eee0a6362018e"
},
{
"name": "money_mouth_face",
"unicode": "1F911",
- "digest": "3ac2f9b5409e1426eef6966938ca04cf78aeffefd43f44b6c86af4af7836e22f"
+ "digest": "5a43973dadf48a89201b1816fea9972c5cfe501a26fe457b6f7eee0a6362018e"
},
{
"name": "money_with_wings",
"unicode": "1F4B8",
- "digest": "f7f1fa502d2f6804169869aeb5ca7f0ea64bc2d6a0204f08875d65da4f8cb332"
+ "digest": "15fcf0595021374ba091ca00efdb4167770da4d421eab930964108545f4edab9"
},
{
"name": "moneybag",
"unicode": "1F4B0",
- "digest": "442db49cda27360d2eb781489c9879730a6094c3267bb0a0a8687d84f8fed078"
+ "digest": "02d708e2f603b0df6f6c169b5c49b3452e1c02e7d72e96f228b73d0b0a20bff4"
},
{
"name": "monkey",
"unicode": "1F412",
- "digest": "3141c971aacbadaba21f970a515e192740212be2a49fa1f5eb0fc4dc576e209f"
+ "digest": "3588a544d6d9e9995b45d60327a1a42002fa1faa4d48224b140facd249af1c67"
},
{
"name": "monkey_face",
"unicode": "1F435",
- "digest": "e2397431d2befe44bf5298fa81d865d80722bf954113bceacc2aa98b84d856e2"
+ "digest": "9e263ef5ca42bb76d1b1d1e3cbf020bcf05023a6e9f91301d30c9eb406363a2a"
},
{
"name": "monorail",
"unicode": "1F69D",
- "digest": "b546153200d6fbe8d65b1b34f62ff4a19b1b6a159eb1b536c5c2ecb56dab0ec9"
+ "digest": "2c9f185babcb4001fcef2b8dfc4a32126729843084d0076c3e3ccdc845ab23ad"
},
{
"name": "mood_bubble",
@@ -7112,102 +7112,102 @@
{
"name": "mortar_board",
"unicode": "1F393",
- "digest": "cb59edb08f75c374088b65284e4d0f77b9bc9573de3e6a5127f865431011e54c"
+ "digest": "d7fbe41d4b340d3564e484aec46a22c9613521414b2ba6eece2180db4d23e410"
},
{
"name": "mosque",
"unicode": "1F54C",
- "digest": "a08ddb74342dea8f79063db6f98ba03eb08fe99481de8ce9123827ca7f17c7f3"
+ "digest": "5f3d3de7feac953a70a318113531c2857d760a516c3d8d6f42d2a3b3b67ed196"
},
{
"name": "motorboat",
"unicode": "1F6E5",
- "digest": "9dbea67bbe2e95dcc68c049a58f87390a44350b32308342615d75214af3d1cef"
+ "digest": "81c156643528c5a94a12d6d478e52a019f5a4e3eb58ee365cdd9d2361a7fdb01"
},
{
"name": "motorcycle",
"unicode": "1F3CD",
- "digest": "8429fb6dfeb873abdffcc179c32d4f23e91c9e6b27b06cd204fd2e83cc11189e"
+ "digest": "354aa8157732184ad50eff9330f7a8915309dc9b7893cc308226adb429311a62"
},
{
"name": "racing_motorcycle",
"unicode": "1F3CD",
- "digest": "8429fb6dfeb873abdffcc179c32d4f23e91c9e6b27b06cd204fd2e83cc11189e"
+ "digest": "354aa8157732184ad50eff9330f7a8915309dc9b7893cc308226adb429311a62"
},
{
"name": "motorway",
"unicode": "1F6E3",
- "digest": "fc05a36c917637c135b0a60db8afcd58cee2b335070fe3888697f8026c9d11a5"
+ "digest": "148c3c13c7c4565453d16e504e0d4b8d007e4f2cad1ab56b1b51fefe39162d17"
},
{
"name": "mount_fuji",
"unicode": "1F5FB",
- "digest": "22bfffef033637b3c9b2fe7e539c74a659d2a49e594d2b33be894da00654d059"
+ "digest": "f8093b9dba62b22c6c88f137be88b2fd3971c560714db15ec053cf697a3820bc"
},
{
"name": "mountain",
"unicode": "26F0",
- "digest": "486cf4e9d5f3913d138fdb7878fe869b39caa3fca53876365957a89dc8f7edb8"
+ "digest": "07423804ad79da68f140948d29df193f5d5343b7b2c23758c086697c4d3a50da"
},
{
"name": "mountain_bicyclist",
"unicode": "1F6B5",
- "digest": "b547b96951b6837df8ae3be1e846f15e7e2ac06d976e1fe7f1442dcc5d3a0942"
+ "digest": "91084b6c887cb7e34f3d7ec30656ecb82c36cc987f53a6c83ccb4c6f7950f96a"
},
{
"name": "mountain_bicyclist_tone1",
"unicode": "1F6B5-1F3FB",
- "digest": "68ce0d55163c7b89ee1d87b752ece127bb25ca9deb3421b31df549a00ac5f69d"
+ "digest": "5d57fcfad61bca26c3e8965eb57602a1993a3117ebdda0f24569af730310ab6e"
},
{
"name": "mountain_bicyclist_tone2",
"unicode": "1F6B5-1F3FC",
- "digest": "5bfa82180bfb8bc4444cf301688aff02884895574a7ba66b398aaf20bde0f101"
+ "digest": "c0da7fb85d99aa01a665f64063cd7e2d994f8a16d3f6fbf52df5d471e771a98a"
},
{
"name": "mountain_bicyclist_tone3",
"unicode": "1F6B5-1F3FD",
- "digest": "33cb64a792123b81a05080465a0ea1035a2cdfdab01c71f5f725a5f92251c3e8"
+ "digest": "b099e7ee84eae44ebc99023fa06bdf37ffa0d69767c7c0163a89f7ced2a26765"
},
{
"name": "mountain_bicyclist_tone4",
"unicode": "1F6B5-1F3FE",
- "digest": "9c3fa4e65dcb0ad69b963292e77c7a75853ae3c1d18a90670f81ffb65b5d020c"
+ "digest": "9d09f7b3899ea44e736f237a161ef8d5170dccfa162a872c59532ceaf65ee007"
},
{
"name": "mountain_bicyclist_tone5",
"unicode": "1F6B5-1F3FF",
- "digest": "871de9e3fddb49b305e5f91000143878b0288c107a125c4e60acf2b6cf8b7f3f"
+ "digest": "71e374981d955056748a60c6d1820b45e9688a156b55318b4ea54a3a67ca801c"
},
{
"name": "mountain_cableway",
"unicode": "1F6A0",
- "digest": "f248ed5bf864f4a81e365b30d2825d2e6fc15a200c4ccf69e9f797341529f955"
+ "digest": "e261c3292758b1c0063c5a0d0c7f5c9803306d2265e08677027e1210506ced94"
},
{
"name": "mountain_railway",
"unicode": "1F69E",
- "digest": "7dd08745ab56c95c3dfcebcca517ff231cef61b670cedf9d7c53f3244c34e30b"
+ "digest": "b0987f8f391b3cbc7a56b9b8945ebfca240e01d12f8fd163877ebebe51d6b277"
},
{
"name": "mountain_snow",
"unicode": "1F3D4",
- "digest": "9939aade3d4d972ba3af16fcc6cc2454978f5426e4c92838734a44db065ce0ff"
+ "digest": "49aac2b851aa6f2bd2ca641efa8060f93e89395357f49d211658d46f5a2b0189"
},
{
"name": "snow_capped_mountain",
"unicode": "1F3D4",
- "digest": "9939aade3d4d972ba3af16fcc6cc2454978f5426e4c92838734a44db065ce0ff"
+ "digest": "49aac2b851aa6f2bd2ca641efa8060f93e89395357f49d211658d46f5a2b0189"
},
{
"name": "mouse",
"unicode": "1F42D",
- "digest": "fb20b3a82f407a6316bbbac68d58018c3d5b93a9a6ae968f44ace18d1c5698d9"
+ "digest": "007dd108507b45224f7a1fad3c1de6ecc75f38d71fc142744611eb13555f5eff"
},
{
"name": "mouse2",
"unicode": "1F401",
- "digest": "87be4099523ec32440e6d091f1193a8ed90730b9fbecaafed4912585bfe7818c"
+ "digest": "f3ed37b639b7c16aae49502bd423f9fdeabaf15bc6f0f74063954b189e176b5d"
},
{
"name": "mouse_one",
@@ -7222,132 +7222,132 @@
{
"name": "mouse_three_button",
"unicode": "1F5B1",
- "digest": "6a5629fee01145211cc8f4e8f59c5f1e61affed38c650502213d76c7d8861b01"
+ "digest": "3724341ac5ad0d01027ef1575db64f1db7619f590ca6ada960d1f2c18dc7fc6a"
},
{
"name": "three_button_mouse",
"unicode": "1F5B1",
- "digest": "6a5629fee01145211cc8f4e8f59c5f1e61affed38c650502213d76c7d8861b01"
+ "digest": "3724341ac5ad0d01027ef1575db64f1db7619f590ca6ada960d1f2c18dc7fc6a"
},
{
"name": "movie_camera",
"unicode": "1F3A5",
- "digest": "d6633b89a637b64d617c3032eed74bb82d3fa732dd9975486b2b5841b473808a"
+ "digest": "f7e285eda35b4431c07951e071643ddc34147cd76640e0d516fbfd11208346e9"
},
{
"name": "moyai",
"unicode": "1F5FF",
- "digest": "bf948c26cd98e2f5e48da363f2924a9d7c217232115a00cec372d0d5293402a8"
+ "digest": "2c1d0662c95928936e6b9ab5a40c6110ff1cea5339f2803c7b63aabc76115afb"
},
{
"name": "muscle",
"unicode": "1F4AA",
- "digest": "c85147efb786bdea3e7d53e2edf6b827280cd9fa881661a6102a614bf5b3579f"
+ "digest": "e4ce52757b2b7982e2516e0e8bf2e2253617cc9f3e6178f1887c61c9039461ba"
},
{
"name": "muscle_tone1",
"unicode": "1F4AA-1F3FB",
- "digest": "38d071df2b25031b61f3605b03c34d2e5d3e35d29f3c4aada14be37e19750eb8"
+ "digest": "4a2fa226a05bb847b62cdd163eb6c2d514d3c2330a727991cf550c0d32b0e818"
},
{
"name": "muscle_tone2",
"unicode": "1F4AA-1F3FC",
- "digest": "dcf11b76c8ffb58dc7e4f9ecd32a4c291d9772d51df2853d41081e041e7e0876"
+ "digest": "a8d5ecce335c782ca5f5e55763c06cfefa1c16c24cd6602237cf125d4ff95e47"
},
{
"name": "muscle_tone3",
"unicode": "1F4AA-1F3FD",
- "digest": "a3d5f8f2dbfc28f9713ee657428ea3292c47d0b22f11a51c13594be22b0f5204"
+ "digest": "070354b443faec3969663b770545fc4cf5ec75148557b2b9d6fc82ab22b43bd1"
},
{
"name": "muscle_tone4",
"unicode": "1F4AA-1F3FE",
- "digest": "eb220fc19be58d16cacc6b721e1011078b03256c0245756f251a4c2bcf50586c"
+ "digest": "8eafcdb6a607aeafa673c257df0d2a1b20f00fc0868d811babcbe784490a0dd3"
},
{
"name": "muscle_tone5",
"unicode": "1F4AA-1F3FF",
- "digest": "4e18708cbd61eaad288f913c86ad2d45108dd4484bc35879c5dcdd075eeb09fd"
+ "digest": "85a1e2b5c89907694240e9c5b9d876a741fa7ba38918c5718273e289cbc40efe"
},
{
"name": "mushroom",
"unicode": "1F344",
- "digest": "a2b252cd759244409d9a8066470059948e2c50b8cc86b59821c1c86b5190f640"
+ "digest": "aaca8cf7c5cfa4487b5fef365a231f98be4bbf041197fc022161bcc8ce6f57c8"
},
{
"name": "musical_keyboard",
"unicode": "1F3B9",
- "digest": "dcb3e84d27bfe373e5ea7ede457908de52002f0fd6105e9f3f5525c54d2a43dd"
+ "digest": "fb0a726728900377d76d94aac9c94dce29107e8e3f1dcb0599d95bce7169b492"
},
{
"name": "musical_note",
"unicode": "1F3B5",
- "digest": "76a0f598f8e251a9dab44f2e14f2b7a6fb0c0c351e0f37862c8c99d380f1c261"
+ "digest": "41288e79b4070bb980281d0e0d1c14d8b144b4aedb2eaadb9f2bebcb4ef892b4"
},
{
"name": "musical_score",
"unicode": "1F3BC",
- "digest": "a132c6b35236005b45c830a42fa97b454d3061c14991c6320f34807f10ba6a4a"
+ "digest": "f0f91b9fa4a2bff7a5a1a11afa6f31cfe7e5fa8b0d6f3cce904b781a28ed0277"
},
{
"name": "mute",
"unicode": "1F507",
- "digest": "73a99b7f9e00f92cab78cd304dee4e893a112c3a6f2285c13d44916ea547458e"
+ "digest": "def277da49d744b55c7cdde269a15aa05315898f615e721ee7e9205d7b8030d6"
},
{
"name": "nail_care",
"unicode": "1F485",
- "digest": "62f721d3610d1647dba4b3f53cd4f2bc4180dae298314c2cca2a6a8ab1664525"
+ "digest": "48b33b1dbbd25b4f34ab2ca07bb99ddaaaa741990142c5623310f76b78c076f9"
},
{
"name": "nail_care_tone1",
"unicode": "1F485-1F3FB",
- "digest": "11b82ed2e6b6619c9b74702fdacfb0ddc91310191c8b89f355c7c69a72673f8f"
+ "digest": "a9ac92a34f407e7dd7c71377e6275e66657f7f42e4b911c540d1a66a02d92ac5"
},
{
"name": "nail_care_tone2",
"unicode": "1F485-1F3FC",
- "digest": "5195c76bccb9149d9080347d785dae2cce947bada5b198fae8c23e42f5553154"
+ "digest": "f295ec85980aaa75818fad619c3d25042146ecbbf361db9e9bb96e7bc202bc73"
},
{
"name": "nail_care_tone3",
"unicode": "1F485-1F3FD",
- "digest": "50eab0bf825c5e00db07a3f5ad26b1bb221f54efb5c55549f392b2f5aec09e5a"
+ "digest": "02ec373052a250977298bae85262177910126cc10de9480f1afa328ac2f65a95"
},
{
"name": "nail_care_tone4",
"unicode": "1F485-1F3FE",
- "digest": "d05a9ccfad02191c89e4cbd00aa48fdaf908c0de6681f4a587d500be448e528f"
+ "digest": "f3d95390ab59caedfda66122bbd0acf3aabedc142fc48352d68900766a7e6f5c"
},
{
"name": "nail_care_tone5",
"unicode": "1F485-1F3FF",
- "digest": "62466354dcf6717a8b9e942ca2c5ad15a26aa815c213e3b01faba9a2e302ecdd"
+ "digest": "009423c97f2aafd24fb8c7c485c58b30bbf9ae6797cc14b80d472b207327b518"
},
{
"name": "name_badge",
"unicode": "1F4DB",
- "digest": "0a1cb0f7d489d3356a4d3e01f9faf78449d82d8ec4595c8639a55c3606c97c40"
+ "digest": "f9f6a4895ff0be8fb2ccc7ad195b94e9650f742f66ead999e90724cfb77af628"
},
{
"name": "necktie",
"unicode": "1F454",
- "digest": "029e1140391ef559a9316021c2db94f05653751fdf9d8f366446467a70fee6df"
+ "digest": "01bb18dc8bfe787daa9613b5d09988cd5a065449ef906099ce3cb308c8a7da68"
},
{
"name": "negative_squared_cross_mark",
"unicode": "274E",
- "digest": "0ba0e705fdeac99edd712db31a8846320b9d2cf53c9cb4d4bcfd22ba4e1488ea"
+ "digest": "1cdaf4abc9adafa089c91c2e33a24e9e647aea0f857e767941a899a16ec53b74"
},
{
"name": "nerd",
"unicode": "1F913",
- "digest": "94efd551700aae8909b8dd7a78a54a33e070d24b2e0a10534353645084614e98"
+ "digest": "9e5f3c93db25cf1d0f9d6e6bd2993161afec6c30573ba3fe85e13b8c84483d66"
},
{
"name": "nerd_face",
"unicode": "1F913",
- "digest": "94efd551700aae8909b8dd7a78a54a33e070d24b2e0a10534353645084614e98"
+ "digest": "9e5f3c93db25cf1d0f9d6e6bd2993161afec6c30573ba3fe85e13b8c84483d66"
},
{
"name": "network",
@@ -7362,157 +7362,157 @@
{
"name": "neutral_face",
"unicode": "1F610",
- "digest": "df01da8501e1f588049c8ed66e504e9abcce83f74ce5790f4d3dc547408f77ee"
+ "digest": "7449430a60619956573e9dc80834045296f2b99853737b6c7794c785ff53d64e"
},
{
"name": "new",
"unicode": "1F195",
- "digest": "24e80abd29750d8b297335cdd4751b6250bb820560cf0392a6cc8783d34db63a"
+ "digest": "e20bc3e9f40726afd0cfb7268d02f1e1a07343364fd08b252d59f38de067bf06"
},
{
"name": "new_moon",
"unicode": "1F311",
- "digest": "2d697e431eac53d6e1ea367b5da03c15fc535cd7e8c214f801fe595b768a8e11"
+ "digest": "dbfc5dcae34b45f15ff767e297cba3a12cb83f3b542db8cfc8dbd9669e0df46c"
},
{
"name": "new_moon_with_face",
"unicode": "1F31A",
- "digest": "ea469a4668ded071f35e5898ae229fdb5d02b0730ce233169b83e22f81292baa"
+ "digest": "c66d347d2222ac8d77d323a07699aff6b168328648db4f885b1ed0e2831fd59b"
},
{
"name": "newspaper",
"unicode": "1F4F0",
- "digest": "0aaf6747a43fb60cd15e6e64ca0eccaade331b376c6fe6712fd5e8294e9868cc"
+ "digest": "c05e986d9cdac11afa30c6a21a72572ddf50fc64e87ae0c4e0ad57ffe70acc5c"
},
{
"name": "newspaper2",
"unicode": "1F5DE",
- "digest": "0ca6b5850091f23295c970815a8e64a52e3c3dae492029ecb1e0726c2693f9bf"
+ "digest": "63db7bcf51effc73e5124392740736383774a4bcfbc1156cf55599504760883d"
},
{
"name": "rolled_up_newspaper",
"unicode": "1F5DE",
- "digest": "0ca6b5850091f23295c970815a8e64a52e3c3dae492029ecb1e0726c2693f9bf"
+ "digest": "63db7bcf51effc73e5124392740736383774a4bcfbc1156cf55599504760883d"
},
{
"name": "ng",
"unicode": "1F196",
- "digest": "4994c9b795033ed788e98c4af571a1dffe28c0a1479e3b42dcae21bb08381b5f"
+ "digest": "34d5a11c70f48ea719e602908534f446b192622e775d4160f0e1ec52c342a35c"
},
{
"name": "night_with_stars",
"unicode": "1F303",
- "digest": "56bb4a59a897c1836ee1a49cc99f468891b790b0f8bce203c201c13bb7b8ae9a"
+ "digest": "39d9c079be80ee6ce1667531be528a2aa7f8bd46c7b6c2a6ee279d9a207c84a4"
},
{
"name": "nine",
"unicode": "0039-20E3",
- "digest": "7e3644a98cb6417a351530c9ce6b368e637a22c847a8c04133897dc1c5d7419f"
+ "digest": "8bb40750eda8506ef877c9a3b8e2039d26f20eef345742f635740574a7e8daa6"
},
{
"name": "no_bell",
"unicode": "1F515",
- "digest": "f4fb42836132000101624fecef8b9358736a0fc76beae460e6986aaa479204fd"
+ "digest": "6542a9a5656c79c153f8c37f12d48f677c89b02ed0989ae37fa5e51ce6895422"
},
{
"name": "no_bicycles",
"unicode": "1F6B3",
- "digest": "b3c258bea7d6988640e3348598c03c97632ca00a11cbf0352995b801ff4a296b"
+ "digest": "af71c183545da2ff4c05609f9d572edb64b63ccba7c6a4b208d271558aa92b0a"
},
{
"name": "no_entry",
"unicode": "26D4",
- "digest": "ac807d54092efdc3aea417790a7d0c50b59800c9ea49b37f1aec6d2e453c5f6d"
+ "digest": "dc0bac1ed9ab8e9af143f0fce5043fe68f7f46bd80856cdec95d20c3999b637d"
},
{
"name": "no_entry_sign",
"unicode": "1F6AB",
- "digest": "5a17d677ec1c7595a7970a1cbe0d20909341b30d3ab31471ced590f51fff1ff7"
+ "digest": "2c1fceef23b62effca68e0e087b8f020125d25b98d61492b1540055d1914fdc3"
},
{
"name": "no_good",
"unicode": "1F645",
- "digest": "8ce921e5e13e1203cf43fdc3e7c5ec1fb2a1f9ff79f21539cff542c80af2e5fe"
+ "digest": "6eb970b104389be5d18657d7c04be5149958c26855c52ea68574af852c5f85c4"
},
{
"name": "no_good_tone1",
"unicode": "1F645-1F3FB",
- "digest": "aab4d354aaac06e8348eb354487c6381e475b44651cb2716660904a36c47a1b6"
+ "digest": "c20a24a1e536240b4dcf90ecb530796de621d7ba1fb9e3fa0f849d048c509c03"
},
{
"name": "no_good_tone2",
"unicode": "1F645-1F3FC",
- "digest": "8fb66b1a7b8f72062794281294515d47471a8c59de300b99d656c3412ca19d64"
+ "digest": "f31a4628c1f2e6a39288fda8eb19c9ec89983e3726e17a09384d9ecc13ef0b4c"
},
{
"name": "no_good_tone3",
"unicode": "1F645-1F3FD",
- "digest": "aeecf73fb9dca24b4002db2802fc9b5a483644c49f834c19f143d4e56ec46c1a"
+ "digest": "959dec1bfdaf37b20a86ab2bcbdbacd3179c87b163042377d966eab47564c0fb"
},
{
"name": "no_good_tone4",
"unicode": "1F645-1F3FE",
- "digest": "fadeb23307d5ccabbf08c848cf81c66c05b152aa32b85f86061caf14760f8eb9"
+ "digest": "efd931f0080adf2e04129c83a8b24fda0ae7a9fa7c4b463686c0b99023620db8"
},
{
"name": "no_good_tone5",
"unicode": "1F645-1F3FF",
- "digest": "cf26d5d6463d0febf4e1f08e343308742ffe0811cfc30c459b87d4cc812f5d04"
+ "digest": "f35df2b26af9baef47c1f8cc97a1b28a58aa7fcb2a13fdac7b2d9189f1e40105"
},
{
"name": "no_mobile_phones",
"unicode": "1F4F5",
- "digest": "3b4ead88beca33f1e303d0a45268849be7aaaff7830b761732c7a5afc5a2de3a"
+ "digest": "a472decd6ac7f9777961c09e00458746b2c04965585e3bee4556be3968e55bcd"
},
{
"name": "no_mouth",
"unicode": "1F636",
- "digest": "2af81a3e07a8b7827a1e58f6f5036ccff2f6e7b0027a4f934c9fa34c6a780963"
+ "digest": "72dda8b1e3ad4b05d9b095f9bd05e95d7ba013906c68914976a4554e8edf5866"
},
{
"name": "no_pedestrians",
"unicode": "1F6B7",
- "digest": "9f9ed90bb8f9964fa8cb0048fc092ecc0612a1994c98d19ef0b5a58607888476"
+ "digest": "062b4a71b338fe09775e465bfba8ac04efbb3640330e8cabe88f3af62b0f4225"
},
{
"name": "no_smoking",
"unicode": "1F6AD",
- "digest": "fb90290ff5c917b7307a97c8ba793d20c61042525cf2f7bfd4cd2a7878aeefa5"
+ "digest": "ae2ebb331f79f6074091c0ee9cd69fce16d5e12a131d18973fc05520097e14ee"
},
{
"name": "non-potable_water",
"unicode": "1F6B1",
- "digest": "c4ddca2ab1a97260e9b2c2aa33fb03455c0e8174541c3a9416fc44143a3ee567"
+ "digest": "32eba0a99b498133c2e4450036f768d3dccaaf5b50adc9ad988757adc777a6a1"
},
{
"name": "nose",
"unicode": "1F443",
- "digest": "308e28b15b7f734f6f184ae367789d7cf258656b24861cf8d5935127d810aa3f"
+ "digest": "9f800e24658ea3cebe1144d5d808cf13a88261f1a7f1f81a10d03b3d9d00e541"
},
{
"name": "nose_tone1",
"unicode": "1F443-1F3FB",
- "digest": "392d24b38ac3edc2d7b83945a60bbe9115a6a97658d8af35281a7cbef79449e8"
+ "digest": "a2d0af22284b1d264eb780943b8360f463996a5c9c9584b8473edf8d442d9173"
},
{
"name": "nose_tone2",
"unicode": "1F443-1F3FC",
- "digest": "409a790339c405770492e49fdb0b5ba34087c27e2f9018ecd845ab078e61476a"
+ "digest": "244dcaa8540024cf521f29f36bd48f933bf82f4833e35e6fa0abf113022038f3"
},
{
"name": "nose_tone3",
"unicode": "1F443-1F3FD",
- "digest": "92b52b479a935f31e460257d809c531edad1a6bb4583ad18233b12c4e45202fe"
+ "digest": "c935b64866f0d49da52035aa09f36ff56d238eb7f5b92205386451056e8ea74f"
},
{
"name": "nose_tone4",
"unicode": "1F443-1F3FE",
- "digest": "78ad2e857792e86cded6ba5620f634f7d1f79a92c82c266e48fab9bd73df3688"
+ "digest": "a87e95fd9319c49e66b6dea0e57319d0ed9921b8d94df037767bf3d5dc7c94f3"
},
{
"name": "nose_tone5",
"unicode": "1F443-1F3FF",
- "digest": "dbef6813c1965d3e93f70f33f118f9950130af21c622cea97ea215a36b4fa73f"
+ "digest": "1e0f9842e0f8ad5805eabd3f35a6038b7a2e49d566a1f5c17271f9cdf467ca60"
},
{
"name": "note",
@@ -7537,12 +7537,12 @@
{
"name": "notebook",
"unicode": "1F4D3",
- "digest": "64bd4a3e7ca7b22fc704c7b7bd4d13540c16bc69b9d8dd76e69e6ad573ab3823"
+ "digest": "fc679d3728f86073d1607a926885dd8b0261132f5c4a0322f1e46ea9f95c8cb8"
},
{
"name": "notebook_with_decorative_cover",
"unicode": "1F4D4",
- "digest": "4b45f28fbde1be5c214a6bc2413abc91db02bccd86f74c21b7f4a4da8b75a46f"
+ "digest": "d822eda4b49cbfa399b36f134c1a0b8dcfdd27ed89f12c50bc18f6f0a9aa56ef"
},
{
"name": "notepad",
@@ -7567,297 +7567,297 @@
{
"name": "notepad_spiral",
"unicode": "1F5D2",
- "digest": "c181b6c1cc6063ec1848e46cbbf1d8b890c53b59cdc5218311ce06889570e727"
+ "digest": "c6a8e16aa62474cef13e5659fddb4afc57e3f79635e32e6020edbee2b5b50f18"
},
{
"name": "spiral_note_pad",
"unicode": "1F5D2",
- "digest": "c181b6c1cc6063ec1848e46cbbf1d8b890c53b59cdc5218311ce06889570e727"
+ "digest": "c6a8e16aa62474cef13e5659fddb4afc57e3f79635e32e6020edbee2b5b50f18"
},
{
"name": "notes",
"unicode": "1F3B6",
- "digest": "bf3868386e17eac40ac7fbabea027042027ff061daafe406c869cdd8ce94641d"
+ "digest": "98467e0adc134d45676ef1c6c459e5853a9db50c8a6e91b6aec7d449aa737f48"
},
{
"name": "nut_and_bolt",
"unicode": "1F529",
- "digest": "fdb9d7408202fad7a52ff21608042c08c3b0beb195999fff233df36a29dc9e96"
+ "digest": "a77bd72f29a7302195dcec240174b15586de79e3204258e3fb401a6ea90563b3"
},
{
"name": "o",
"unicode": "2B55",
- "digest": "8e119dba4130bd33b3ee5c862fb4fa5a691173911ffee51cb9359fee3398e330"
+ "digest": "2387e5fd9ae4c2972d40298d32319b8fa55c50dbfc1c04c5c36088213e6951dd"
},
{
"name": "o2",
"unicode": "1F17E",
- "digest": "00d751124c25633611055bd61e74fc3f3d1779f0d09e1e707837686f613367b4"
+ "digest": "6a9ccb0bf394e4d05ffda19327cee18f7b9ed80367fc7f41c93da9bb7efab0bf"
},
{
"name": "ocean",
"unicode": "1F30A",
- "digest": "9b1fbfd2a64f417d0c2cb91085b29a12d14e15844bc21798bdee938bb7bf6222"
+ "digest": "1a9ca9848d4fb75852addfc10bf84eccf7caa5339714b90e3de4cb6f2518465e"
},
{
"name": "octopus",
"unicode": "1F419",
- "digest": "3fdfbc02f47ad434bdeb7f3a15cd4e8f8118ee1cd754627e358f1c2f4616f5e3"
+ "digest": "0fcc65c12f4b29ea75a8c4823d20838a7e6db6978fdcb536943072aa1460bc59"
},
{
"name": "oden",
"unicode": "1F362",
- "digest": "afed1c5166943e5803602ffacc67652e3b29ee4222a6c36aba2daf88bd21ad3c"
+ "digest": "089974cb13a0bef6a245fc73029c5ed5153fd4caae0177b835f779e32200b8aa"
},
{
"name": "office",
"unicode": "1F3E2",
- "digest": "dc1836ef152d88fd628df18db770594f5dbc8d7f20d6ce982588b25b78b19c92"
+ "digest": "3633a2e91036362e273eef4e0cfbdbbb4cb1208afe2cfa110ebef7b78109a66f"
},
{
"name": "oil",
"unicode": "1F6E2",
- "digest": "f8b7626cb09e229203105b9c8c7f3fbb38c0650021092fc50115ad517248644a"
+ "digest": "00b94d33bcc9b9e8a5d4bd6e7f7e2fced9497ce05919edd5e58eafbc011c2caa"
},
{
"name": "oil_drum",
"unicode": "1F6E2",
- "digest": "f8b7626cb09e229203105b9c8c7f3fbb38c0650021092fc50115ad517248644a"
+ "digest": "00b94d33bcc9b9e8a5d4bd6e7f7e2fced9497ce05919edd5e58eafbc011c2caa"
},
{
"name": "ok",
"unicode": "1F197",
- "digest": "6b05bbab4a7104541c2f4bce553884d17ae0ad07589b19d6b53b6949c14f2269"
+ "digest": "5f320f9b96e98a2f17ebe240daff9b9fd2ae0727cd6c8e4633b1744356e89365"
},
{
"name": "ok_hand",
"unicode": "1F44C",
- "digest": "9981f32ef200b011a10f6bfa2066c41b6b5e7bcd6c3c21647980b640bc1fa93b"
+ "digest": "d63002dce3cc3655b67b8765b7c28d370edba0e3758b2329b60e0e61c4d8e78d"
},
{
"name": "ok_hand_tone1",
"unicode": "1F44C-1F3FB",
- "digest": "e5933a9b64b03ce0634f15f02ff7b6424530dbdc0e283461e0c9992d0c2ca2ad"
+ "digest": "ef1508efcf483b09807554fe0e451c2948224f9deb85463e8e0dad6875b54012"
},
{
"name": "ok_hand_tone2",
"unicode": "1F44C-1F3FC",
- "digest": "4c04741c9f2c8731da8df3015e9aae00061a01848c2d22aab1e9853c271deed3"
+ "digest": "1215a101a082fd8e04c5d2f7e3c59d0f480cb0bedd79aeab5d36676bfe760088"
},
{
"name": "ok_hand_tone3",
"unicode": "1F44C-1F3FD",
- "digest": "216dc5a72f9e34bbb7b39f680c388bd5b52abf9b41b843342e53e285b7933076"
+ "digest": "6fe0ed9fb42e86bb2bed4cb37b2acacacda1471fb1ee845ad55e54fb0897fbf4"
},
{
"name": "ok_hand_tone4",
"unicode": "1F44C-1F3FE",
- "digest": "7139de7ec9d5a962cf87b9fbbeef3a53aa482bb840ab3b64d8d0da81bdc19886"
+ "digest": "bfb9041c49d95e901a667264abaf9b398f6c4aa8b52bf5191c122db20c13c020"
},
{
"name": "ok_hand_tone5",
"unicode": "1F44C-1F3FF",
- "digest": "e18b0a1bc5d970cc63466bd6da6e9f855db37d1eada3230d19f600c1f5a402a3"
+ "digest": "1c218dc04d698da2cbdd7bea1ca3f845f9b386e967b7247c52f4b0f6ec8f5320"
},
{
"name": "ok_woman",
"unicode": "1F646",
- "digest": "3b2fa732d9c9addb056f136192428e99d805d4cb1c7dab724fd552c7e93197e4"
+ "digest": "3f8bd4ce2c4497155d697e5a71ebdc9339f65633d07fa9a7903e1bd76cfa4ba1"
},
{
"name": "ok_woman_tone1",
"unicode": "1F646-1F3FB",
- "digest": "017aca3797701b043a44f22e67dcad8b531a3ca14e629ae0d2fbc601ed3e49cb"
+ "digest": "1660cd904ccd2ecdc6f4ba00527f7d4ec8c33f3c6183344616f97badae4c3730"
},
{
"name": "ok_woman_tone2",
"unicode": "1F646-1F3FC",
- "digest": "036bed032bc5a616668775cda0d5640c810e2836aa28009c8e8bf2b487259c59"
+ "digest": "7ba5fddd1e141424fac6778894dfc5af28e125839c58937c69496f99cd2c4002"
},
{
"name": "ok_woman_tone3",
"unicode": "1F646-1F3FD",
- "digest": "d9a4414caddda43d1a36828cfbecce5f2b7e5c1b67b4a47991b2ae0a34cf7ab7"
+ "digest": "1d972b8377c52f598406f59ab1e5be41aaf8f027e1fefba3deda66312ccd6a9b"
},
{
"name": "ok_woman_tone4",
"unicode": "1F646-1F3FE",
- "digest": "942e1b9aa495c4c4de0804e4d4348422201299d649e5d65829ba4a308880df1c"
+ "digest": "a176328d8f53503aa743448968afd21d72ffd3510555526a3fb38d6b30ee7c15"
},
{
"name": "ok_woman_tone5",
"unicode": "1F646-1F3FF",
- "digest": "e8d0fb5b999d5d63404493aa505b5af2260c76001023431d5e788773d0a9e2de"
+ "digest": "13cfc1b589c57e81f768ee07a14b737cafc71407a7eb0956728b2ec4b1df14c4"
},
{
"name": "older_man",
"unicode": "1F474",
- "digest": "620f763325827acbeb9d57798ef55d87827d0dfc77b84d942e25bc5057f2cbfe"
+ "digest": "4c0462b199bf26181c9e4d2d4cb878a32b0294566941212efc67362d0645f948"
},
{
"name": "older_man_tone1",
"unicode": "1F474-1F3FB",
- "digest": "e0f35c12362eae503d1c30a345c3a4978196d351d8a1eb9d5f107c60ea4bbf52"
+ "digest": "99baa083f78cb01166d0a928d0b53682be14be04c29fc17bef14aac1a73a61e6"
},
{
"name": "older_man_tone2",
"unicode": "1F474-1F3FC",
- "digest": "671766ce9fa47c3fa009d4f138344c87d73032a1c38e48614c663f8ea5d0f673"
+ "digest": "5b4ce713e8820ba517fe92c25f3b93e6a6bf3704d1f982c461d5f31fc02b9d3d"
},
{
"name": "older_man_tone3",
"unicode": "1F474-1F3FD",
- "digest": "6ff4885ef8c416b8970780a691fef74c8d89421ab11e0aa8c522c33e1c67fbe8"
+ "digest": "0eff72b3226c3a703c635798ee84129a695c896fa011fe1adbc105312eecc083"
},
{
"name": "older_man_tone4",
"unicode": "1F474-1F3FE",
- "digest": "0ae7d4e316dcd4d27a5a6cdaabab88a4f992bd1b75f6ceaeb5b906ed1eb5269c"
+ "digest": "ad9ba82b0c5d3b171b0639ee4265370dbddff5e0eeb70729db122659bb8c8f84"
},
{
"name": "older_man_tone5",
"unicode": "1F474-1F3FF",
- "digest": "abe2757bd5e35f30d2a6daec09637ea5382a46d14d239b77282e9bf874229b57"
+ "digest": "5eb0a7467cc40e75752e11fd5126b275863dc037557a0d0d3b24b681e00c2386"
},
{
"name": "older_woman",
"unicode": "1F475",
- "digest": "3ed599443eed25399aac999fc234c9e97f8fb6ec567e37a553c26e01021b097c"
+ "digest": "c261fdf3b01e0c7d949e177144531add5895197fbadf1acbba8eb17d18766bf6"
},
{
"name": "grandma",
"unicode": "1F475",
- "digest": "3ed599443eed25399aac999fc234c9e97f8fb6ec567e37a553c26e01021b097c"
+ "digest": "c261fdf3b01e0c7d949e177144531add5895197fbadf1acbba8eb17d18766bf6"
},
{
"name": "older_woman_tone1",
"unicode": "1F475-1F3FB",
- "digest": "7421c5dba67cfd1eeabb2fa8faf4aa0d615d23f191cf7d7c0ad9c1fa884edfda"
+ "digest": "1f2bb9e42270a58194498254da27ac2b7a50edaa771b90ee194ccd6d24660c62"
},
{
"name": "grandma_tone1",
"unicode": "1F475-1F3FB",
- "digest": "7421c5dba67cfd1eeabb2fa8faf4aa0d615d23f191cf7d7c0ad9c1fa884edfda"
+ "digest": "1f2bb9e42270a58194498254da27ac2b7a50edaa771b90ee194ccd6d24660c62"
},
{
"name": "older_woman_tone2",
"unicode": "1F475-1F3FC",
- "digest": "65edeef25648ac7f8be535df06af1286441691fa15176e99a6e83fc779aa2cde"
+ "digest": "2e28198e9b7ac08c55980677ed66655fd899e157f14184958bebd87fcd714940"
},
{
"name": "grandma_tone2",
"unicode": "1F475-1F3FC",
- "digest": "65edeef25648ac7f8be535df06af1286441691fa15176e99a6e83fc779aa2cde"
+ "digest": "2e28198e9b7ac08c55980677ed66655fd899e157f14184958bebd87fcd714940"
},
{
"name": "older_woman_tone3",
"unicode": "1F475-1F3FD",
- "digest": "5d27bbcc5796227a9caec1c7612d3f691055655b96f7303e420839463d76c269"
+ "digest": "c968be0170f7e0c65d4f796337034cfb1daba897884da6fad85635ab5b6edf67"
},
{
"name": "grandma_tone3",
"unicode": "1F475-1F3FD",
- "digest": "5d27bbcc5796227a9caec1c7612d3f691055655b96f7303e420839463d76c269"
+ "digest": "c968be0170f7e0c65d4f796337034cfb1daba897884da6fad85635ab5b6edf67"
},
{
"name": "older_woman_tone4",
"unicode": "1F475-1F3FE",
- "digest": "75b858e910175fc0233503d672120fd43ac035ba3fd2052fbb44df39f6e3695c"
+ "digest": "3596a6fa9a643bf79255afcd29657b03850df8499db9669b92ce013af908af44"
},
{
"name": "grandma_tone4",
"unicode": "1F475-1F3FE",
- "digest": "75b858e910175fc0233503d672120fd43ac035ba3fd2052fbb44df39f6e3695c"
+ "digest": "3596a6fa9a643bf79255afcd29657b03850df8499db9669b92ce013af908af44"
},
{
"name": "older_woman_tone5",
"unicode": "1F475-1F3FF",
- "digest": "9da1cf10a605c470877d7f4a840f99344b1ec2e7b1ec7db61e930cde77025e3b"
+ "digest": "c8998cb3dbd15e22bd1d6dad613d109ce371d9ffca3657e1a8afe5aeb30c1275"
},
{
"name": "grandma_tone5",
"unicode": "1F475-1F3FF",
- "digest": "9da1cf10a605c470877d7f4a840f99344b1ec2e7b1ec7db61e930cde77025e3b"
+ "digest": "c8998cb3dbd15e22bd1d6dad613d109ce371d9ffca3657e1a8afe5aeb30c1275"
},
{
"name": "om_symbol",
"unicode": "1F549",
- "digest": "c8c1c9d445b1fc50a627b71bee21fba978e04532e4685ec032a0174f51fc12bb"
+ "digest": "5ead73bea546ba9ba6da522f7280cc289c75ff5467742bdba31f92d0e1b3f4e6"
},
{
"name": "on",
"unicode": "1F51B",
- "digest": "08e1159a68d3334a87ffa75b9e70826cb557d0f73a2c1d08f4c3d60476ecacc8"
+ "digest": "9cc61a6b31a30c32dab594191bf23f91e341c4105384ab22158a6d43e6364631"
},
{
"name": "oncoming_automobile",
"unicode": "1F698",
- "digest": "6bff7f40fe223df6d16c7512532b8aa6f83e8c13e1007b63eb9aabf774c1a322"
+ "digest": "557c9cacdc3f95215d4f7a6f097a2baa7c007cb9c519492a6717077af4ca6b56"
},
{
"name": "oncoming_bus",
"unicode": "1F68D",
- "digest": "127a357fcd96ce4b9ab11c3dba95d8ff811bab193dd8ba38efb7067a44752ce8"
+ "digest": "059f28ce6bfb337e107db5982cbd2004844450ef20b4a54b9ca3cb738360ab05"
},
{
"name": "oncoming_police_car",
"unicode": "1F694",
- "digest": "57cb70e05e70c1f68ab42259f307ed9782c2b9d6e35d2dff2895aa23d7eb6b04"
+ "digest": "aee79306a0d129cfc1980f58db80391eb46d2d7d5f814bf431414dc7680cab72"
},
{
"name": "oncoming_taxi",
"unicode": "1F696",
- "digest": "174967ae4c3d5881d2408c71c020f704e933190af4caef5d2908e9ac382f35ea"
+ "digest": "84351489fc86d980b8d3eb9ec4e81120fe700b3ac01346daebe2b7aeb9607a55"
},
{
"name": "one",
"unicode": "0031-20E3",
- "digest": "113b9d87c3e37c9c54e49cecccbfc40c15fb97fd03a51505df85e48b78702b2b"
+ "digest": "d5d3fff04e68a114ff6464ee06fc831f3f381713045165f62a88d5e8215c195b"
},
{
"name": "open_file_folder",
"unicode": "1F4C2",
- "digest": "def93715203aed464211798d773732895a19389a94a2e7ed43e7f229b2aab7da"
+ "digest": "96cfc322ee4903ae8cec07604811742245fd7d14f00bb70276d39d29c48bed28"
},
{
"name": "open_hands",
"unicode": "1F450",
- "digest": "7c60a37ae11727c998908199b8709e52593b931843aef942f37b306b1edca12a"
+ "digest": "a6c131da2040b48103cea14f280e728675da50fa448d2b3f3438fcbb5bf5596a"
},
{
"name": "open_hands_tone1",
"unicode": "1F450-1F3FB",
- "digest": "09ffa9b3f28fc56a71e4e711bdfc87ce1a56721229377e71f1c00224523f8b9b"
+ "digest": "867128dff2fa9b860c10c6b792f989f0c057928783696062378f834c0ef89d85"
},
{
"name": "open_hands_tone2",
"unicode": "1F450-1F3FC",
- "digest": "21ecaba9f086bcb7eb07c17c2b2621bcd1ca28c57f79032d5e0eba356494cc85"
+ "digest": "487ff2745b03d49bb3b1d0acd86ba530fd8cc3f467ca3fa504f88f0ef1cbbc01"
},
{
"name": "open_hands_tone3",
"unicode": "1F450-1F3FD",
- "digest": "c7dbb8c44f78f7793b202ec215fee42b7e1e555d659fbf402383500217b89656"
+ "digest": "cb8cddc8b8661f874ac9478289d16cc41406b947bb87f3363df518a588a53e16"
},
{
"name": "open_hands_tone4",
"unicode": "1F450-1F3FE",
- "digest": "867451d42492ab2277687447f421f744530b9ea057312326353fec39c94b18fd"
+ "digest": "17dcc2c07230846a769f3c79ce618a757c88b9b58c95c6c5b2d7f968814d447d"
},
{
"name": "open_hands_tone5",
"unicode": "1F450-1F3FF",
- "digest": "56335506cf68e29150cb68d7ebbb4a92aed390018966669a8144d20ae0d6cfe3"
+ "digest": "36b2493d67c84cea4f3f85a3088c6abcfd35cf99f7aeaeedfafa420ee878e3d2"
},
{
"name": "open_mouth",
"unicode": "1F62E",
- "digest": "f05fdf998e8b5c0b00ebd8b5ab17a67f5c0a45275f31a201af74e8ab0c2f7ba9"
+ "digest": "1906c5100ae0c8326ca5c4f9422976958a38dadd8d77724d68538a25d9623035"
},
{
"name": "ophiuchus",
"unicode": "26CE",
- "digest": "98c61bb0c36d60c476d42d5e074297662e8d141dcab7004a5bd63c359eed3b84"
+ "digest": "6112e2a1656b1cb8bd9a8b0dfa6cbf66d30cae671710a9ef75c821de344aab2b"
},
{
"name": "optical_disk",
@@ -7872,27 +7872,27 @@
{
"name": "orange_book",
"unicode": "1F4D9",
- "digest": "86d150ea3d62183ab7dfe2851cf7f4d1ae769b7ecbb1987b0f463e639e429598"
+ "digest": "41141b08d2beceded21a94795431603c47fd7d42a3a472a2aa8b2bb25fa87ebf"
},
{
"name": "orthodox_cross",
"unicode": "2626",
- "digest": "9c861285ca6d699cd2c72b6df44ec2b1e64138152f19c66e32df1ce770ff2e83"
+ "digest": "c16372102f0169dd6d32eb2b27a633aaee74e4e0fddcf723c15ad97f9dc6075c"
},
{
"name": "outbox_tray",
"unicode": "1F4E4",
- "digest": "b6a6015d5d7d528af485de23ff4518dc35408def1cc49bc6c9b01d880d613985"
+ "digest": "e47cb481a0ffcb39996f32fd313e19b362a91d8dda15ffca48ac23a3b5bb5baf"
},
{
"name": "ox",
"unicode": "1F402",
- "digest": "cbcfe5c8c4d6b939e24e18e610785f171bb9410441e02c2eeb1bceb0a6246daf"
+ "digest": "d13bc60552190bb9936bf32d681bdc742439b702a09cfc62137ea09a98624aed"
},
{
"name": "package",
"unicode": "1F4E6",
- "digest": "4023cffce85384217a73609f457aec013876e689c44bcfff0bcc35f3e4e1ab00"
+ "digest": "e82bf5accebb65136e897c15607eef635fb79fd7b2d8c8e19a9eb00b6786918c"
},
{
"name": "page",
@@ -7902,17 +7902,17 @@
{
"name": "page_facing_up",
"unicode": "1F4C4",
- "digest": "71a0872bf1b13c58746f9b41655227c75be107ab6083c0dce13cb16444af22e7"
+ "digest": "3884868bdcb2f29615b09a13a30385cbc5269379094a54b5a7e8a5f4e8ce905a"
},
{
"name": "page_with_curl",
"unicode": "1F4C3",
- "digest": "cb4210464faea946c7b07db7067c7fc98920f778cf57721388f5362942ba3029"
+ "digest": "3d6257670189f841ad1fa45415c34feb2433b2cb35bb435c4ee122ce89b39669"
},
{
"name": "pager",
"unicode": "1F4DF",
- "digest": "209dbdc19aa650ecacc0569e17a9123c9a1e39df59c9b4120f3b0888b63cd6f1"
+ "digest": "e21c756cc1c58ebc1b37ebcd38e22a25b31e2e81306c6f18285d6a7671f9eb12"
},
{
"name": "pages",
@@ -7922,132 +7922,132 @@
{
"name": "paintbrush",
"unicode": "1F58C",
- "digest": "73eb33184f5f495d6c2699fafc1a8680069f82a70fbe519290c3a2ce30d1aee9"
+ "digest": "fc0da7a25b726b8be9dd6467953e27293d2313a21eeff21424c2a19be614fff2"
},
{
"name": "lower_left_paintbrush",
"unicode": "1F58C",
- "digest": "73eb33184f5f495d6c2699fafc1a8680069f82a70fbe519290c3a2ce30d1aee9"
+ "digest": "fc0da7a25b726b8be9dd6467953e27293d2313a21eeff21424c2a19be614fff2"
},
{
"name": "palm_tree",
"unicode": "1F334",
- "digest": "1589ff4b1b87296edc0118e4aa67b3b504ed85a5b8d47e7d0c3e309d0bbf8cd6"
+ "digest": "90fedafd62fe0abf51325174d0f293ebb9a4794913b9ba93b12f2d0119056df1"
},
{
"name": "panda_face",
"unicode": "1F43C",
- "digest": "050ee87892f56ff485f460bc6c3846d98a0ca7083d2cf0b8ab24772b672273f2"
+ "digest": "56a4b84abe983bd6569be1b81ac5e43071015fd308389a16b92231310ae56a5b"
},
{
"name": "paperclip",
"unicode": "1F4CE",
- "digest": "1463607a59345973f009fa53a719e2264b95743560adb99737bef29b1d133a95"
+ "digest": "d1e2ce94a12b7e8b7a9bba49e47ddc7432ec0288545d3b6817c7a499e806e3f0"
},
{
"name": "paperclips",
"unicode": "1F587",
- "digest": "7071e031f4a100c3cb3573fbfa375360043f0276289a0818f2ffaf71b3580040"
+ "digest": "70cefa0d0777f070e393e9f95c24146fe2dd627f30fa3845baa19310d9291fe2"
},
{
"name": "linked_paperclips",
"unicode": "1F587",
- "digest": "7071e031f4a100c3cb3573fbfa375360043f0276289a0818f2ffaf71b3580040"
+ "digest": "70cefa0d0777f070e393e9f95c24146fe2dd627f30fa3845baa19310d9291fe2"
},
{
"name": "park",
"unicode": "1F3DE",
- "digest": "d257f0f1b1a0134573f80ba1a5f522a91c320ee7f93a1cb64877c077e7e19b50"
+ "digest": "444dce8014e0817ddd756c36a38adfbbf7ae4c6aa509e4cae291828f0716d5e7"
},
{
"name": "national_park",
"unicode": "1F3DE",
- "digest": "d257f0f1b1a0134573f80ba1a5f522a91c320ee7f93a1cb64877c077e7e19b50"
+ "digest": "444dce8014e0817ddd756c36a38adfbbf7ae4c6aa509e4cae291828f0716d5e7"
},
{
"name": "parking",
"unicode": "1F17F",
- "digest": "e1d2cfd1c57ea85003ca4df066cbba4e506bf6c4d6c790e27b2f78ad8443fabf"
+ "digest": "9f1da460a7dd58b26beab8cf701be2691fb812208fbc941c71daa35be1507c2f"
},
{
"name": "part_alternation_mark",
"unicode": "303D",
- "digest": "b3cc2e803b255e858417345ba6ba52a1c22f511b483fec11b5d68c4432f759b6"
+ "digest": "956da19353bb38fd4dfe0ab5360679a9035d566858fb5de62887b85c75fb8eef"
},
{
"name": "partly_sunny",
"unicode": "26C5",
- "digest": "484990f5e1a3b14c731e7bd4b0b4a1c10cd5fb54ac7cf2751f40c8bf59d7e2b4"
+ "digest": "8fb9a6d2caf9e0cce58447762f0dfd6aa0b581b2e83fea6411348e0cbc8cf3c4"
},
{
"name": "passport_control",
"unicode": "1F6C2",
- "digest": "224e8ef60d4d6587721727555de324948fb5b6c1cb5cc4b546960983d1ec85c4"
+ "digest": "d9be6eed2c90e1c89171c42d70a06485fdf86a4c68833371832cc1f6897fadd0"
},
{
"name": "pause_button",
"unicode": "23F8",
- "digest": "edd605ffaa39a7905ed0958b7cc69f00f5b271e579198d2df1746ad1b3648272"
+ "digest": "143221d99e82399ed7824b6c5e185700896492058b65c04e4c668291de78b203"
},
{
"name": "double_vertical_bar",
"unicode": "23F8",
- "digest": "edd605ffaa39a7905ed0958b7cc69f00f5b271e579198d2df1746ad1b3648272"
+ "digest": "143221d99e82399ed7824b6c5e185700896492058b65c04e4c668291de78b203"
},
{
"name": "peace",
"unicode": "262E",
- "digest": "e0ee8a5c9fb18d5db6841b21527ed8fd955abdff9ffdb7b2684dca22107015fc"
+ "digest": "65181429e373c1f0507bbd98425c1bec0c042d648fb285a392460cbce60f44d4"
},
{
"name": "peace_symbol",
"unicode": "262E",
- "digest": "e0ee8a5c9fb18d5db6841b21527ed8fd955abdff9ffdb7b2684dca22107015fc"
+ "digest": "65181429e373c1f0507bbd98425c1bec0c042d648fb285a392460cbce60f44d4"
},
{
"name": "peach",
"unicode": "1F351",
- "digest": "a3f4fd5ff02e0a03104ab54456ee1a7521858ee68443856ee10e0972e5b6aaa5"
+ "digest": "768d1f4f29e1e06aff5abb29043be83087ded16427ce6a2d0f682814e665e311"
},
{
"name": "pear",
"unicode": "1F350",
- "digest": "7a7a72568d53677cd1fff4d9e58e63327a742fa16d22a2bef03b4a6fa378d3b3"
+ "digest": "b7c9cf90bb979649b863d2f4132f1b51f6f8107d42e08fb8b4033fea32844948"
},
{
"name": "pen_ballpoint",
"unicode": "1F58A",
- "digest": "6becdc6f622c774bb09b7e7592bba2123ecccc9de32a35f0b18b50d7d54109cb"
+ "digest": "aacb20b220f26704e10303deeea33be0eec2d3811dcba7795902ca44b6ae9876"
},
{
"name": "lower_left_ballpoint_pen",
"unicode": "1F58A",
- "digest": "6becdc6f622c774bb09b7e7592bba2123ecccc9de32a35f0b18b50d7d54109cb"
+ "digest": "aacb20b220f26704e10303deeea33be0eec2d3811dcba7795902ca44b6ae9876"
},
{
"name": "pen_fountain",
"unicode": "1F58B",
- "digest": "8c78cf0c2bd1d5e309d2d3356ff207e3fc76ca18dd6b90762cb62f6afbc95c6a"
+ "digest": "3619913eab2b6291f518b40481bb3eca0820d68b0a1b3c11fb6a69c62b75a626"
},
{
"name": "lower_left_fountain_pen",
"unicode": "1F58B",
- "digest": "8c78cf0c2bd1d5e309d2d3356ff207e3fc76ca18dd6b90762cb62f6afbc95c6a"
+ "digest": "3619913eab2b6291f518b40481bb3eca0820d68b0a1b3c11fb6a69c62b75a626"
},
{
"name": "pencil",
"unicode": "1F4DD",
- "digest": "62b7ee5d9352114d09ee6f2c9a4c5e8b79f775a6c509e82ddfcdd61e13716249"
+ "digest": "accbc3f1439b7faa4411e502385f78a16c8e71851f71fc13582753291ffb507c"
},
{
"name": "memo",
"unicode": "1F4DD",
- "digest": "62b7ee5d9352114d09ee6f2c9a4c5e8b79f775a6c509e82ddfcdd61e13716249"
+ "digest": "accbc3f1439b7faa4411e502385f78a16c8e71851f71fc13582753291ffb507c"
},
{
"name": "pencil2",
"unicode": "270F",
- "digest": "aa2c572772187fee1f9125bb0950f5ce8a61f7dd2647258c40b4077ee5feb498"
+ "digest": "9ca1b56b5726f472b1f1b23050ed163e213916dac379d22e38e4c8358fe871e0"
},
{
"name": "pencil3",
@@ -8062,7 +8062,7 @@
{
"name": "penguin",
"unicode": "1F427",
- "digest": "095de34b3f6a2521a342c21f5f2551a0092bf47429801c15b7bbf0913924f412"
+ "digest": "a1800ab931d6dc84a9c89bfab2c815198025c276d952509c55b18dd20bd9d316"
},
{
"name": "pennant_black",
@@ -8087,147 +8087,147 @@
{
"name": "pensive",
"unicode": "1F614",
- "digest": "2d9e7f1eed14dcc86674cec78e992567a40d0f223fc67d722b91eebcd1251269"
+ "digest": "d237deff9f5ead8a0b281b7e5c6f4b82e98cc30c80c86c22c3fdc6160090b2f2"
},
{
"name": "performing_arts",
"unicode": "1F3AD",
- "digest": "a202755bab6427433975589bb8b63e61e5d7f55c6242676d8000e91eedabc55e"
+ "digest": "d7c7bc9213e308ca26286cbbd8012e656b0f9b00293758faf1bfccc4c5ceabed"
},
{
"name": "persevere",
"unicode": "1F623",
- "digest": "686ef3fc70ce8294d02a764ebd75b69f25cca6bff6b92e7905130366d22f6d8a"
+ "digest": "c361509c9b8663af19a02a1ffff61b1b0d0b4bd75d693ce3d406b0ca1bde1ca0"
},
{
"name": "person_frowning",
"unicode": "1F64D",
- "digest": "16e8fbf22c0b4c237d0d45202fa32d1ebd04760a5b6975c9c9b477321ccb0e12"
+ "digest": "b37be8bd95f21a6860ad3f171b8086125ab37331b382d87bcdb4cd684800546b"
},
{
"name": "person_frowning_tone1",
"unicode": "1F64D-1F3FB",
- "digest": "a143b865976ce3cf307db854cfd1ca58c3832df0eee5e9b0ab307cf4f24ba3db"
+ "digest": "3d5e78a367f9673baed2a86bc11cf04fd44394aadb65291fa51ade8dca318427"
},
{
"name": "person_frowning_tone2",
"unicode": "1F64D-1F3FC",
- "digest": "4e7050d8a38019ba2293f66b9930e6a7e35dacf3b3bc9431edb586a0d9ea8054"
+ "digest": "7456c414c65ad6b6f11855f68a2eedc18113526f86862c4373202397cb1bed2c"
},
{
"name": "person_frowning_tone3",
"unicode": "1F64D-1F3FD",
- "digest": "0750015d3ac1b5954d31e36cd59c70b6ed9f4df698082484b7ac59eb0b9964b0"
+ "digest": "c86cf2d6951f1e6a7c786a74caaf68a777cf00e88023e23849d4383f864ae437"
},
{
"name": "person_frowning_tone4",
"unicode": "1F64D-1F3FE",
- "digest": "18d6cc92d0990624218d38d6eeed60bccb371d0fc9f1c889e9476b3b0c44b5e8"
+ "digest": "944e96ced645ced8db6bb50120c7e37ed46b6960d595cbfe964c81803efa83aa"
},
{
"name": "person_frowning_tone5",
"unicode": "1F64D-1F3FF",
- "digest": "4a898199cbaf083d37511f51d8a1d2560b7a20c62a1b09087831da7010fbd093"
+ "digest": "4bd0ea571be6ef9f0493784ef0d12d5e47bc2d6ac610fb42c450bf3d87fb2948"
},
{
"name": "person_with_blond_hair",
"unicode": "1F471",
- "digest": "67d95a0801c65f62db55fa80ab35dec65c239601a44bf5f5902e4645f126770e"
+ "digest": "a7f94ede2e43308108c2260d83fc10121dda09a67f94a0a840e6d7bba7fd5616"
},
{
"name": "person_with_blond_hair_tone1",
"unicode": "1F471-1F3FB",
- "digest": "e79717bfe30a26eafc082a75fa7547d8f2ad3c123fb2d75a95e75f0ce7ecbd0c"
+ "digest": "00a116357a7878554c83e5bade4bddfa9cfabf76a229efa19cbb58e0d216219c"
},
{
"name": "person_with_blond_hair_tone2",
"unicode": "1F471-1F3FC",
- "digest": "c4a1961c292149ab6e1fd54a7894398599bf855de97a05ee4e836a86a400deb3"
+ "digest": "df509ebe92ed3138b9d5bd4645eff4b13f77f714cf62bb949c59eff1adc00019"
},
{
"name": "person_with_blond_hair_tone3",
"unicode": "1F471-1F3FD",
- "digest": "e2707d0cf778bee5b72d861ec76430eb1cf9f9820f066ee6327574d5697f445e"
+ "digest": "6f328513f440a0c8cd1dc44596a5028fd8f306bdaf57c1e6f3aa94a3aa262b3c"
},
{
"name": "person_with_blond_hair_tone4",
"unicode": "1F471-1F3FE",
- "digest": "94da43f0b12ef4a98dabec096ff1184b0a9b5b6ee55824d257e5112cc7e88730"
+ "digest": "32df1a577815b009696643ad80d063cc97b35d54add6d4e5517fc936f6da9ee8"
},
{
"name": "person_with_blond_hair_tone5",
"unicode": "1F471-1F3FF",
- "digest": "9e096a210ea720d32bc6a7005cd77f8b314ccf817fc3060da2e1796de39e9d60"
+ "digest": "2e270bb39187d8e36a33f4aa4d6045308189595fafc157cf7993e82d7ce93442"
},
{
"name": "person_with_pouting_face",
"unicode": "1F64E",
- "digest": "8c3199a422250d2db9a163156191ed2c6697d7f31699e2efe19e05ca26e5d225"
+ "digest": "57e9a6e5f82121516dc189173f2a63b218f726cd51014e24a18c2bdfeeec3a0b"
},
{
"name": "person_with_pouting_face_tone1",
"unicode": "1F64E-1F3FB",
- "digest": "3e1f09bbf607381c992739ea92dd35cbd26b1bbc705a7d21b7c3156f50e9d8b3"
+ "digest": "d10dadb1ac03fc2e221eff77b4c47935dc0b4fe897af3de30461e7226c3b4bbc"
},
{
"name": "person_with_pouting_face_tone2",
"unicode": "1F64E-1F3FC",
- "digest": "b5fc1cf3fdc5ff01105ee2452db90baa6a52c1e42f3795b2836c3e35197ece1f"
+ "digest": "efface531537ab934b3b96985210a2dac88de812e82e804d6ec12174e536d1cc"
},
{
"name": "person_with_pouting_face_tone3",
"unicode": "1F64E-1F3FD",
- "digest": "e8ec2539c458a8283c8c1050634c432b6363f3e64b68ba4c977994782f09b564"
+ "digest": "7ff26ece237216b949bfa96d16bd12cfd248c6fd3e4ed89aa6c735c09eafaeff"
},
{
"name": "person_with_pouting_face_tone4",
"unicode": "1F64E-1F3FE",
- "digest": "5cab7a29699decd45682583446c2bf56ddcd69cd16e14db661b526a4076dfa17"
+ "digest": "045c04105df41d94ff4942133c7394e42ff35ef76c4ccb711497ab77ae6219f2"
},
{
"name": "person_with_pouting_face_tone5",
"unicode": "1F64E-1F3FF",
- "digest": "3caebd3626fd77d849859d1c99a747f80a2b59bfa5c1854494f1ce0485539a94"
+ "digest": "783ee37f146fcf61d38af5009f5823cf6526fe99ed891979f454016bce9dd4ba"
},
{
"name": "pick",
"unicode": "26CF",
- "digest": "24a3e8f592435b97272e6d134ea5503dce3012811659c4aadbad4e45d9fba679"
+ "digest": "7f0ec5445b4d5c66cf46e2a7332946cce34bd70e9929ac7a119251a7f57f555d"
},
{
"name": "pig",
"unicode": "1F437",
- "digest": "50b55fc74e8f6c89c6e04609381c99a660748908f0ef015f5da37089678ad0c3"
+ "digest": "51362570ab36805c8f67622ee4543e38811f8abb20f732a1af2ffbff2d63d042"
},
{
"name": "pig2",
"unicode": "1F416",
- "digest": "e8189fb678608e8b9d69e11d2566f9a4765cbdff99ec8e66df30c7a2dabf742f"
+ "digest": "67010e255f28061b9d9210bcdab6edc072642ad134122a1d0c7e3a6b1795a45b"
},
{
"name": "pig_nose",
"unicode": "1F43D",
- "digest": "7e299cb49a771884f5065c68733a5a1fe354a54cff009127230177f1717af4a5"
+ "digest": "0b21cac238bf4910939fbea9bed35552378c1b605a3867d7b85c1556dbda22a9"
},
{
"name": "pill",
"unicode": "1F48A",
- "digest": "53ae3379cc6721744979122569f157a5a13aa6b48e081a89f17b2d90134efe9e"
+ "digest": "cb00be361aaba6dbcf8da58bd20b76221dd75031362ecae99496b088ed413a7f"
},
{
"name": "pineapple",
"unicode": "1F34D",
- "digest": "ceda8ffa4a41594f28a4e69d03f8a1daeb2ba20740f0b8c56447cae833eea035"
+ "digest": "621d4d4c52b59e566c2e29ed7845c8bd2d1da0946577527342097808d170dd70"
},
{
"name": "ping_pong",
"unicode": "1F3D3",
- "digest": "dd2a84716c93410a285ff759bfbc2dc31a10f90b203c7a657b908e5949e89a39"
+ "digest": "943a858bd054c81a08a08951f8351c27c8009b85a9359729c7362868298b58e1"
},
{
"name": "table_tennis",
"unicode": "1F3D3",
- "digest": "dd2a84716c93410a285ff759bfbc2dc31a10f90b203c7a657b908e5949e89a39"
+ "digest": "943a858bd054c81a08a08951f8351c27c8009b85a9359729c7362868298b58e1"
},
{
"name": "piracy",
@@ -8242,322 +8242,322 @@
{
"name": "pisces",
"unicode": "2653",
- "digest": "75f11b9a094196b54a242420362fa7c0aeba7cfc497b187e1aaaba96d93684a7"
+ "digest": "453c3915122a4b6b32867056d2447be48675a84469145c88d52f8007fcb0861a"
},
{
"name": "pizza",
"unicode": "1F355",
- "digest": "ac94ae1c034f7b854ce2a483e1c219d101a84336f5065342f4824ff32ba705c4"
+ "digest": "169bc6c1e1d7fdab1b8bf2eab0eeec4f9a7ae08b7b9b38f33b0b0c642e72053a"
},
{
"name": "place_of_worship",
"unicode": "1F6D0",
- "digest": "4fabc307b7e35f94288f6d53985485662a4814b11a9a382f0a3873d41b1290d3"
+ "digest": "daf271d36a38ee8c0f8b9de84c128ab8b25a5b7df8f107308d0353c961f2c644"
},
{
"name": "worship_symbol",
"unicode": "1F6D0",
- "digest": "4fabc307b7e35f94288f6d53985485662a4814b11a9a382f0a3873d41b1290d3"
+ "digest": "daf271d36a38ee8c0f8b9de84c128ab8b25a5b7df8f107308d0353c961f2c644"
},
{
"name": "play_pause",
"unicode": "23EF",
- "digest": "d69e8cdec33447283cf65d343b986115e27681d781b721db7894e5c587ca18ad"
+ "digest": "af1498f34a3d6e0da8bbd26ebaa447e697e2df08c8eb255437cf7905c93f8c42"
},
{
"name": "point_down",
"unicode": "1F447",
- "digest": "685f46a643be7f3033896e59a822f87d61ce50db6969bcdbacc743215a96bb7a"
+ "digest": "4ecdb3f31c16dc38113b8854ec1a7884613b688a185ebdf967eab9a81018f76d"
},
{
"name": "point_down_tone1",
"unicode": "1F447-1F3FB",
- "digest": "d3dd2608fe17d5649c960fcf8dbdb68466908d80fa349b7947b457da2a27ebb1"
+ "digest": "c74a7c94367cddbfa840542dc0924adeb0d108be0c7fde8c25fb95d69115d283"
},
{
"name": "point_down_tone2",
"unicode": "1F447-1F3FC",
- "digest": "67ab236a14f6d63abcdb26433a66a183d223186c21ebc9f978fab50165ebe271"
+ "digest": "dc4bda0726d85418b974addb42738f437fbb9cf16e5815cdbab3859c4ada6cae"
},
{
"name": "point_down_tone3",
"unicode": "1F447-1F3FD",
- "digest": "c8a2368f2cedb5bbb5cc0195b97fbf3787747637bf6e77bdc9a4edf4a3f22a04"
+ "digest": "e460f81a501376d2f0ed1d45e358c5ed03ba049e8f466e4298afb4f3ca6d24dc"
},
{
"name": "point_down_tone4",
"unicode": "1F447-1F3FE",
- "digest": "6a92eab3bc8f950fa423e690f54a352887bda92f01e91c62eb3f3a9544c10cd8"
+ "digest": "4bc91cd771f24e0f897a9d8b18f323fec9a82da0fc2429c4a7e4e6a9d885a0a3"
},
{
"name": "point_down_tone5",
"unicode": "1F447-1F3FF",
- "digest": "6ad329f156414f421d6f8cf5e2a68d34b7a41f90d80e8e66b15bcbd3788126c7"
+ "digest": "7e47c6bc73250f36dc7ae1c1c09e7b41f30647b9d0ff703a53a75cc046b5057d"
},
{
"name": "point_left",
"unicode": "1F448",
- "digest": "cb520d6bba4c2b3bd7911315c9efce3261d048ff090437d7e24c9c5a7255043e"
+ "digest": "b5a7e864a0016afbadb3bec41f51ecf8c4af73cc20462e1a08b357f90bca6879"
},
{
"name": "point_left_tone1",
"unicode": "1F448-1F3FB",
- "digest": "81813901bdaa8d261277f79aff9e9a21beb80a5855899941820b25f70786ec21"
+ "digest": "9f1868272a10a2b738c065be5d30241643324550cfd47baf01c7a09060e66d31"
},
{
"name": "point_left_tone2",
"unicode": "1F448-1F3FC",
- "digest": "ecdc3dea0d644290aa7e0dab758c215822482a482ba35d825a33152453593c1e"
+ "digest": "bf0d58c68178a2c2c01d4a6235a1a66b90073cea170f9f6fe2668b6dd68424f7"
},
{
"name": "point_left_tone3",
"unicode": "1F448-1F3FD",
- "digest": "84e73b6a37755016271c255eba164f349dbd2a2badf5d9ac1c6f4cbfcae589f0"
+ "digest": "34d28c97bc8f9d111d14e328153c4298fc32cf18e39e20aacaec17846645ed90"
},
{
"name": "point_left_tone4",
"unicode": "1F448-1F3FE",
- "digest": "d16800499b6c6ede94256796b1de8a8f723879f636849856b3bd8b7a092b5576"
+ "digest": "c40c8436316915d516c53bb1c98a469528cefd98baa719be7e748c4608cbbcc9"
},
{
"name": "point_left_tone5",
"unicode": "1F448-1F3FF",
- "digest": "18b7108066cebf2d4090f29e595a2f01db94bd210f3b1d61dc269ec249a749b9"
+ "digest": "c410fe32e4ce0ded74845a54b86090e59e5820d457837b16e175b36cc71ecb46"
},
{
"name": "point_right",
"unicode": "1F449",
- "digest": "866180bf31e92de32aba336d5b5ce81773a29cdaadada1d93c944cf9ad9783bc"
+ "digest": "44d9251ab41f2f48c2250c44a47f92b3476a71f13fbbbfb637547db837fd5a49"
},
{
"name": "point_right_tone1",
"unicode": "1F449-1F3FB",
- "digest": "ebe2e4bf6bd46a5798b9a845a4ed055911c4fe58dbeacc4d39d6ea63e28e7cc9"
+ "digest": "9fcce259eb81c0b52ec7796b98a1653194e3a9021a1d338df1dbbab7522fc406"
},
{
"name": "point_right_tone2",
"unicode": "1F449-1F3FC",
- "digest": "b638662a67b1c6adde4f5abc789aae010b178404cdd1b71fcc982cdf8307c655"
+ "digest": "9d00a0b1cfc435674dc56065b3d28d28839196977504cf20581205351d8708f2"
},
{
"name": "point_right_tone3",
"unicode": "1F449-1F3FD",
- "digest": "32c6ca2f992416ab2c36672dfbc1c0de8f102c77a13496dd8d63736a7b0261d2"
+ "digest": "e3026a70630ba73d76892a055a80cac2f78d509faddce737f802d2abefa074ba"
},
{
"name": "point_right_tone4",
"unicode": "1F449-1F3FE",
- "digest": "89bd6828e9b82408a3829d49fa43332e2599f7d10bc6e5b14b750ef03267b173"
+ "digest": "ea508fde90561460361773b4e1b8e80874667b19ac115926206e7c592587cb76"
},
{
"name": "point_right_tone5",
"unicode": "1F449-1F3FF",
- "digest": "390525048a12b0efa22de550c800e439b0deaad03f1f31155d179aef093354af"
+ "digest": "d59cdb2864eb2929941ecd233f8b8afcddc30fbd4594e5f9acf6386ae06ac12c"
},
{
"name": "point_up",
"unicode": "261D",
- "digest": "31b5ca1303c1afabe1db322b24f73b23f3568c87a364f61c82f6e0c858c090e9"
+ "digest": "b69ff4f650989709f2185822d278c7773672bd9eb4a625da80f3038a2b9ce42b"
},
{
"name": "point_up_2",
"unicode": "1F446",
- "digest": "55c237054aa347c9847f3f3f577eb755db55dfcf793aa7de0f8f868574d70e8f"
+ "digest": "e83cd9eff2af5125a25f5a306c3ee3cfea240add683b5c36a86a994a8d8c805c"
},
{
"name": "point_up_2_tone1",
"unicode": "1F446-1F3FB",
- "digest": "dc07e7732d973de96ae3b08b14c19e20b6c1aea7f5a30e7198679b750422e914"
+ "digest": "b02ec3e7e04a83bfb769cffb951cbf32aa78e56fa5a51c097f9326df9e08ed33"
},
{
"name": "point_up_2_tone2",
"unicode": "1F446-1F3FC",
- "digest": "af2211fc4a1bd51d1e76f7bc43a6fa87bdd24e4295c52fdbdb01c1ca670a6cd7"
+ "digest": "32994b85c8b4a1383ca985ebc3382be88866cea1ff1315adfb71fb05e992a232"
},
{
"name": "point_up_2_tone3",
"unicode": "1F446-1F3FD",
- "digest": "917701169b3fb3e1b6e14a68e9572b25998ef2e38abac9ad8cf30100f8ea0dac"
+ "digest": "9e263bcfb82ada34ff85291f36e64e66b86760fb11a4e0c554e801644d417d6d"
},
{
"name": "point_up_2_tone4",
"unicode": "1F446-1F3FE",
- "digest": "20843904764c6c3e55792cce0c55c76f72b97788c5229cad655ebf1f2873b439"
+ "digest": "3edc92130a0851ac7b5236772ce7918d088689221df287098688e1ed5b3ff181"
},
{
"name": "point_up_2_tone5",
"unicode": "1F446-1F3FF",
- "digest": "1d0cca546027c717da50f90da65757af46fe7cd4e397da9b8e203446f707208d"
+ "digest": "cabb3b7da9290840ef59d0c8b22625bdb2e94842f01b0a575ccbc348f3069d77"
},
{
"name": "point_up_tone1",
"unicode": "261D-1F3FB",
- "digest": "5ede60379dee23166c6b834d73da8b55268e330f67058843b8a3705dca6ed71a"
+ "digest": "e496fda349072f8b321ceb7a251175f7244c3076661f5ede48ea75ba1acf8339"
},
{
"name": "point_up_tone2",
"unicode": "261D-1F3FC",
- "digest": "c94a15ef848d410aa5d32b8d0e453b59682fde6f39e6705cbb81cf0829833a81"
+ "digest": "5a8081323f3baa67e6431e21e16a36559b339f5175d586644e34947f738dd07a"
},
{
"name": "point_up_tone3",
"unicode": "261D-1F3FD",
- "digest": "d319ce72876d97a3b1d4bc7c0679e546a983f02145d723a0da5ed0b73a51cfe7"
+ "digest": "07bf0cea812eb226b443334e026e13d1ec23e013478f4af862a3919703107842"
},
{
"name": "point_up_tone4",
"unicode": "261D-1F3FE",
- "digest": "9171a27f86f27fd144347a17153fb56e30bd32e67a8f10f8c1f32a40cad4e009"
+ "digest": "1fbbd71433108143ee157d0fdadd183f7f013bafa96f0dd93b181e1fd5fd4af2"
},
{
"name": "point_up_tone5",
"unicode": "261D-1F3FF",
- "digest": "a894f87da4c3d33d5e6e74d003a33ec60c453db6507fe05d22235f807ead27d6"
+ "digest": "ad068ef32df32f8297955490a9a90590a0f93ed5702a052cd0d8f6484c6cc679"
},
{
"name": "police_car",
"unicode": "1F693",
- "digest": "7999869cb75be404fc34942b6f9d8e84fa7e259aa892a1e8e1652a5f02cceea6"
+ "digest": "0909be1bd615ae331a7cce71e16dee3ca663c721d5170072c593cb7c76f9f661"
},
{
"name": "poodle",
"unicode": "1F429",
- "digest": "8a568d8688bf19b440b7c1b49fcfe6672b8f75af0031d89ab6212623430acadb"
+ "digest": "f1742fdf3fd26a8a5cfeaba57026518dacaad364cbd03344c4000a35af13e47a"
},
{
"name": "poop",
"unicode": "1F4A9",
- "digest": "140ce75a015ede5e764873e0ae9a56e7b2af333eddca0fe2796b14545c620258"
+ "digest": "857a61c872138d359a7fe8257bb26118afa49d75186eca2addb415d07c92b3ec"
},
{
"name": "shit",
"unicode": "1F4A9",
- "digest": "140ce75a015ede5e764873e0ae9a56e7b2af333eddca0fe2796b14545c620258"
+ "digest": "857a61c872138d359a7fe8257bb26118afa49d75186eca2addb415d07c92b3ec"
},
{
"name": "hankey",
"unicode": "1F4A9",
- "digest": "140ce75a015ede5e764873e0ae9a56e7b2af333eddca0fe2796b14545c620258"
+ "digest": "857a61c872138d359a7fe8257bb26118afa49d75186eca2addb415d07c92b3ec"
},
{
"name": "poo",
"unicode": "1F4A9",
- "digest": "140ce75a015ede5e764873e0ae9a56e7b2af333eddca0fe2796b14545c620258"
+ "digest": "857a61c872138d359a7fe8257bb26118afa49d75186eca2addb415d07c92b3ec"
},
{
"name": "popcorn",
"unicode": "1F37F",
- "digest": "12264cb16fca9317e3ba8d5924a2c8f15f790e36d2f29e7b12aaaf77e1beb73d"
+ "digest": "684f1b7ef34ea7ca933aed41569bc6595a19ef0d546a1b7b9e69f8335540b323"
},
{
"name": "post_office",
"unicode": "1F3E3",
- "digest": "5e2d896cd646a2eecd5596af9e44ca1fa2745de5cedaf0f6d193b8243201c6cc"
+ "digest": "54398ee396c1314a7993b1cb1cba264946b5c9d5a7dbb43fd67286854d1d1a0f"
},
{
"name": "postal_horn",
"unicode": "1F4EF",
- "digest": "339aa61fa1567a1d159bb8204d15db889fbb6cc1106f6e1991b4a184d1bc1fc7"
+ "digest": "0ea12f44f3bae9a14bde3b37361b48bd738d2f613bb1b53a9204959b70e643f8"
},
{
"name": "postbox",
"unicode": "1F4EE",
- "digest": "ef1a6543fccb9f1009cc3782c51883e51167721a0b49e8ba21e8e6049b216906"
+ "digest": "bbc424ae8d46de380d7023a43ea064002fd614657d00330d3503275827ac87e2"
},
{
"name": "potable_water",
"unicode": "1F6B0",
- "digest": "4a2379835660dfa8b6780d662a10d1effab710f471eb9b5e6ade4772ba7e5aeb"
+ "digest": "dbe80d9637837377cc2a290da2e895f81a3108cc18b049e3d87212402c1c2098"
},
{
"name": "pouch",
"unicode": "1F45D",
- "digest": "cbd47ec1a65f5c642773d8ea2e7e57f7041a2d7ed9df05fbdd7bc8743c6dece6"
+ "digest": "9f012b90310b4a072b6a8fa2c64def087b5f7ffffaafc36e1856ba943a170351"
},
{
"name": "poultry_leg",
"unicode": "1F357",
- "digest": "d416e9464bd58073bd3e32eb06c0da96905609f47b9d667acdc0810e94237584"
+ "digest": "1445ec4f5e68a19e5a84e5537dca8190d62409070c954d112e6097f1a6b7f054"
},
{
"name": "pound",
"unicode": "1F4B7",
- "digest": "1ac491bb8a91613b2b1faaac4e7b4bc794d2abef69ac79de17d54c824c3ef826"
+ "digest": "eb11b83eb52adb0a15e69a3bc15788a2dc7825dedee81ac3af84963c9dd517b5"
},
{
"name": "pouting_cat",
"unicode": "1F63E",
- "digest": "ba28d75401d5bb98773acd35aaf173356bae4d5a5520a226559478138364ebdf"
+ "digest": "8822abedf3499cf98278d7eeea0764d1100ec25cad71b4b2e877f9346f8c8138"
},
{
"name": "pray",
"unicode": "1F64F",
- "digest": "fb0df9c1566014bd2df2a1afd59366b896f20c03ca3516e02e4be44ea556c8ea"
+ "digest": "735b79dab34ac2cf81fd42fdcd7eb1f13c24655e5e343816d5764896c03edeea"
},
{
"name": "pray_tone1",
"unicode": "1F64F-1F3FB",
- "digest": "c6d8cb46e65ad13a92e85f97e018176fd89513f23e899e15d1ad09e3b4009f4b"
+ "digest": "e8b6103450215e8566797f150978355e297deade4eb47a6371f7a7bc558fed9d"
},
{
"name": "pray_tone2",
"unicode": "1F64F-1F3FC",
- "digest": "2cd68cbe1ba3254f173ec8136af79cae64873bd0f20480158c3e6babd5a1a442"
+ "digest": "ee8baacd95d7e8dbad8a1f2d9a12e36c98f3d518db5d3b117d0a18290815e62b"
},
{
"name": "pray_tone3",
"unicode": "1F64F-1F3FD",
- "digest": "d2e81863f74a87b96335fb108e7b206f28ed18185362ab4d42a3b0523801398b"
+ "digest": "ae8c0caa9aca0a6c44069e76a7535c961d0284cd701812f76bbd2bd79ce2bd53"
},
{
"name": "pray_tone4",
"unicode": "1F64F-1F3FE",
- "digest": "ad1b91254b101d872325c325ebd1f2a6257cfe22e83de88e29dd16ffac191979"
+ "digest": "64f7b3178b8cd6f6a877ed583539eefe068fa87a0dd658fdcd58c8bc809f7e17"
},
{
"name": "pray_tone5",
"unicode": "1F64F-1F3FF",
- "digest": "23f40a11321decbdc6a1d274b9ad571041d261d364d13d1063c306e73ad52254"
+ "digest": "5bc8cdce937ac06779c87021423efcec4f602aa4a39dba90b00de81033005332"
},
{
"name": "prayer_beads",
"unicode": "1F4FF",
- "digest": "cb6f8700154f75749cf2642a25c03e255dc18428baf8b57f6bd807c92b83e28d"
+ "digest": "80177091264430cbcf7c994fbe5ee17319d1a58d933636cc752a54dafcf98a05"
},
{
"name": "princess",
"unicode": "1F478",
- "digest": "47b93eb52d757c3c000d9760391ecb942776d883b28050d833fa11612483d8ee"
+ "digest": "efabd28480a843c735f0868734da2f9ce28133933b02ab07b645498f494f3f80"
},
{
"name": "princess_tone1",
"unicode": "1F478-1F3FB",
- "digest": "1e4073c2abdf51a61a1a85a3e063541fe96e9b9ec36ec6f7fb9c98deeb230869"
+ "digest": "52b88b99ba64f82e8f36e2a1827c85145e4fcd6863478c2345fe9fa9e8901cdf"
},
{
"name": "princess_tone2",
"unicode": "1F478-1F3FC",
- "digest": "6a0a5dc447cd887798f908c15972e7a12d28d81f168b92bcb105786ac253bea0"
+ "digest": "7e44289404693668f20e681fcdc2e516512d54a69c627eedae958f69dfe6eea9"
},
{
"name": "princess_tone3",
"unicode": "1F478-1F3FD",
- "digest": "2f08d22fdfc7a7d66fcd87ae716b811f43077f5bb17fef87f5b7e2aa93700d70"
+ "digest": "96c9a9857348d7a1a8be899c50d55b352b9a9fd5c65e4777bfa199fe7929d41c"
},
{
"name": "princess_tone4",
"unicode": "1F478-1F3FE",
- "digest": "02129211bf7bf7ff6de35913b7069aee151532d878b8c4f7e24c012e5b09d4b4"
+ "digest": "67696f96be60f2a36598072172d2db197d007e6c1ac3acef526a5ce6d59bf3f7"
},
{
"name": "princess_tone5",
"unicode": "1F478-1F3FF",
- "digest": "d676f103600b69dbfdb469469a77b9d561ec460ff862befa58ab30ddc909c9f7"
+ "digest": "007f624e2fad91bb57ce32ecd35213a796d71807f3b12f3f1575bf50e6a50eeb"
},
{
"name": "printer",
"unicode": "1F5A8",
- "digest": "c44402c87071f8d31d3997abab53ab9f8f7c11434e747380928814ceb6b0a417"
+ "digest": "5e5307e3dc7ec4e16c9978fb00934c99c4adefca7d32732a244d1f2de71ce6f8"
},
{
"name": "prohibited",
@@ -8572,57 +8572,57 @@
{
"name": "projector",
"unicode": "1F4FD",
- "digest": "fc361282f367926254c08150b02cb8fda7fa8d2c9c939d9360c78bf19a4f982e"
+ "digest": "7f8e1fdb89584849a56ee34c62cab808af48b7bd4823467d090af4657a2e0420"
},
{
"name": "film_projector",
"unicode": "1F4FD",
- "digest": "fc361282f367926254c08150b02cb8fda7fa8d2c9c939d9360c78bf19a4f982e"
+ "digest": "7f8e1fdb89584849a56ee34c62cab808af48b7bd4823467d090af4657a2e0420"
},
{
"name": "punch",
"unicode": "1F44A",
- "digest": "5759db1d7093744c74b840bbb4761fb025d6633f8fa539bcb35dcf54fc05ceb6"
+ "digest": "c7e7edf6d64f755db3f02874354f08337b3971aff329476d19ac946e0b421329"
},
{
"name": "punch_tone1",
"unicode": "1F44A-1F3FB",
- "digest": "793b3fa2a43c23b2c1e1b48b86ae35e8c4024cd065fac0a0a5ada87cb78d6de3"
+ "digest": "c9ba508b0c36041047473782acfedab5af40dd7946b33daf4d8d54c726e06a11"
},
{
"name": "punch_tone2",
"unicode": "1F44A-1F3FC",
- "digest": "6fc2467e99982ab00b0c352c6f7793d34faf17b16a0312082c9bd1f0709e3938"
+ "digest": "d53011cd2f3334c7b3fffdfe1e2b8cc1c832c74306e1ac6d03f954a1309d7d0b"
},
{
"name": "punch_tone3",
"unicode": "1F44A-1F3FD",
- "digest": "bf747b29952550c5b4d3807b9ed85b5e5d4bcc3265b0e214791f7db547f861fb"
+ "digest": "f7522347094e0130ed8e304678106574dbd7dd2b6b3aeb4d8a7a0fef880920b2"
},
{
"name": "punch_tone4",
"unicode": "1F44A-1F3FE",
- "digest": "3b6c0ccb682552f32d6744c438e3af04a1732c67a74bcafb14c723cf526fed87"
+ "digest": "3e62bdd426f3e6ff175ce3b8dd6f6d3998d9c1506128defa96b528b455295b47"
},
{
"name": "punch_tone5",
"unicode": "1F44A-1F3FF",
- "digest": "945bae1aa3587cd1dc57d1ec4da18c67a59e0e7150dcc8735e5357b4ea1234ac"
+ "digest": "7d9bff777dc4ec41ac132b1252fa08cf92a398c8dc146c4a5327b45d568982d8"
},
{
"name": "purple_heart",
"unicode": "1F49C",
- "digest": "e0eb886e74f22d40d059ff3a089d472af53c6c53de380f428cca140dfd046345"
+ "digest": "a6bf01de806525942be480e45a4b2879f91df8129b78a1b8734d4f917bcab773"
},
{
"name": "purse",
"unicode": "1F45B",
- "digest": "67d82ff9a4d76148b9d98538d4b786f880058a556e650ec3f93e1632aa42aaa7"
+ "digest": "2b785f36e01875d66cfda2192c8c53606e7224a7c869a4826b62cb61613d60c8"
},
{
"name": "pushpin",
"unicode": "1F4CC",
- "digest": "c4de129d5d8744caffeb2f499fcc0bc6b551843938f8166ffecd0de00bda66e3"
+ "digest": "c3f7d7008be6bab8dc02284d4d759abf7aafbb3dbbe3a53f0f5b2ff685af88f8"
},
{
"name": "pushpin_black",
@@ -8632,202 +8632,202 @@
{
"name": "put_litter_in_its_place",
"unicode": "1F6AE",
- "digest": "b26d3b68bd62d30ecfe75cfaf309a7a0f91e92db0aa18b0b97b97baf0609d4e6"
+ "digest": "f52a57d6f1bada7b6e6b9a6458597d70cb701c01e1120d8cb1d7ff65e01d405c"
},
{
"name": "question",
"unicode": "2753",
- "digest": "258e3169bae177fb0f01ed5f9b933f7f02dd2673e12a316af44a0c3729a78a2c"
+ "digest": "40050a1fd29bed321fd601d13dc33de5d6084121f1d873b29bde9dc3d823a310"
},
{
"name": "rabbit",
"unicode": "1F430",
- "digest": "9817a7454aeda77d28f63eb13c0dc0a6d9e6c9abe3dcf538b4b3477e494cddb6"
+ "digest": "678ad953a7ab8f618c59051449a67c965d1f04f42dd6f6669adaf3fadebd080c"
},
{
"name": "rabbit2",
"unicode": "1F407",
- "digest": "67ba57a31b0768a2118faabdcb088f96f1441e1132397f65b6937d523ff7dabb"
+ "digest": "19b1f5108292472434cc7a49efac4ea9275779735c7aeb0f15c36021d5998ca0"
},
{
"name": "race_car",
"unicode": "1F3CE",
- "digest": "2e9828e3884c79ad7e9e1173d3470790f3f56cfa08ef4e38deff45db0728c66c"
+ "digest": "46f4814259d3d17ff35c04110e73e5327aee99f4711cd459ca1ee951508da3a6"
},
{
"name": "racing_car",
"unicode": "1F3CE",
- "digest": "2e9828e3884c79ad7e9e1173d3470790f3f56cfa08ef4e38deff45db0728c66c"
+ "digest": "46f4814259d3d17ff35c04110e73e5327aee99f4711cd459ca1ee951508da3a6"
},
{
"name": "racehorse",
"unicode": "1F40E",
- "digest": "36aa3c7123ee7e15600657166032b21b8edeb192cf6d3ada39b5c65001f7fc40"
+ "digest": "a57b7aca35347ada8225eeee06b70cfd040484104963b4df56ea8fec690576b0"
},
{
"name": "radio",
"unicode": "1F4FB",
- "digest": "b1403f9a883405b909208f52c9474c2d3923681ea0b02609a6e9dc12460319a5"
+ "digest": "9245951dd779cdd141089891b15a90d3999a6358acf1fc296aa505100f812108"
},
{
"name": "radio_button",
"unicode": "1F518",
- "digest": "9bcdac17b3620331a32f9bb876812231a701eb5a7f696e7d875f877ab92159fc"
+ "digest": "565bec59198df2592e96564c6e314d3cde33c47b453db1bec6c5d027b5cb4fd9"
},
{
"name": "radioactive",
"unicode": "2622",
- "digest": "5ad8e8594617c0153672a76421deb836e05c6098020c33af3f975f8fcfe216e4"
+ "digest": "0ed6634057824e0cfd10b2533753e3632b0624341a7eac8d9835706480335581"
},
{
"name": "radioactive_sign",
"unicode": "2622",
- "digest": "5ad8e8594617c0153672a76421deb836e05c6098020c33af3f975f8fcfe216e4"
+ "digest": "0ed6634057824e0cfd10b2533753e3632b0624341a7eac8d9835706480335581"
},
{
"name": "rage",
"unicode": "1F621",
- "digest": "02ac70551fc51478884c133b29539cae58b463c760db38c0aeec1bdf5b282312"
+ "digest": "d97ba6bd08eec46dbc7199f530c945b73a87a878e35397b0a3e4f2b45039e89e"
},
{
"name": "railway_car",
"unicode": "1F683",
- "digest": "8490e2ecf94c7c1d1e22fea0d80cc18a49648741009e51984f583b17bbd022e2"
+ "digest": "2cddc08d555e7fc24e312c3d255ed013fbf9cd2974a6918369c32554049ba2be"
},
{
"name": "railway_track",
"unicode": "1F6E4",
- "digest": "63ee881cc775d5b2711082b6c96ab44d5204c5d390afd6d8ee97e52aeeaa5e5e"
+ "digest": "0da351b6d4e75c6beeaef1225e151d9580d4b5c41dfa1cf192715bf3cec981d7"
},
{
"name": "railroad_track",
"unicode": "1F6E4",
- "digest": "63ee881cc775d5b2711082b6c96ab44d5204c5d390afd6d8ee97e52aeeaa5e5e"
+ "digest": "0da351b6d4e75c6beeaef1225e151d9580d4b5c41dfa1cf192715bf3cec981d7"
},
{
"name": "rainbow",
"unicode": "1F308",
- "digest": "bbd8ecc8d0737948969a3539d2d202e599404e509f1a21bdbb0a0c41c2540522"
+ "digest": "a93aceb54e965f35e397e8c8716b1831614933308d026012d5464ee42783ed4d"
},
{
"name": "raised_hand",
"unicode": "270B",
- "digest": "4192881a0d613b4fcb19b1c2d8b83aadee6f0b12170721c8dd7b1ccef6540199"
+ "digest": "5cf11be683aea985d5ba51fbd44722c2327311bfe26b61c3d441c90f5d5a195a"
},
{
"name": "raised_hand_tone1",
"unicode": "270B-1F3FB",
- "digest": "df2e046c99dceb9184c50a777b403d72bfb25ff473d6a4e20bb9a731db64ed8d"
+ "digest": "865afca29b57577fed8fe8c2be57b74254a008c8cf34194680be2759239b5f5d"
},
{
"name": "raised_hand_tone2",
"unicode": "270B-1F3FC",
- "digest": "ed179299a1c397cd51cf6067d6795d71a3831d35e1ec9eacbf0286c8992c1e7a"
+ "digest": "832169a0b626a682a58a3b998f68413657b4962c1fab05f1fdc2668e82727210"
},
{
"name": "raised_hand_tone3",
"unicode": "270B-1F3FD",
- "digest": "cacbd0ddef65bc01a41bd921ea159f8cd89050309b10f15780d6199f79434a54"
+ "digest": "3959a873ad7671de82c615c4ed840b011e67baafb2bab7dd16859608d3e83cb1"
},
{
"name": "raised_hand_tone4",
"unicode": "270B-1F3FE",
- "digest": "04c934c7a55b83bcfa7f3880fc1f6aa0f188090c37b9670e6775a512a1cf59e9"
+ "digest": "db542f65d076ccf3dbfca27cb7c2f135a8bf7a487a81a04873e70172bdfcd579"
},
{
"name": "raised_hand_tone5",
"unicode": "270B-1F3FF",
- "digest": "da0c4283b7b19861237c023234c6db28045b8f5a5971acb015733e08e2940e86"
+ "digest": "88ca884d14baaae48df21d75c22d82fb15bdc395e42026f5ca34cd65e5ae8674"
},
{
"name": "raised_hands",
"unicode": "1F64C",
- "digest": "308e475f38558e73bd66e28693d77478caa5bca4360cffaffc2a97b5858c56ba"
+ "digest": "2ee73466a3f5079e542857fe6f5497e9f87753a81854985ce3356a8d3da1d8b8"
},
{
"name": "raised_hands_tone1",
"unicode": "1F64C-1F3FB",
- "digest": "e39b9bc49dccc127e44f543e98961fcf5bcd44d6e216741bcd10ec3667263c84"
+ "digest": "43e73c60f040a66374b8ec98f3629a90d13ae9f472446ed7676cd5573e824f4b"
},
{
"name": "raised_hands_tone2",
"unicode": "1F64C-1F3FC",
- "digest": "f376ab13071ffdc11888ec221ef5b4de546ca0f60bd9ae30bf3da4066c220462"
+ "digest": "fcc5255bb2b06dc82d6878e74cf34e8ce118c70004a06d39a980683772b98c52"
},
{
"name": "raised_hands_tone3",
"unicode": "1F64C-1F3FD",
- "digest": "67694325a43e629c00fa9bd2ff7e19f84f216b2855ae2cf097762dfa7aca25e6"
+ "digest": "3ee3e0aafef486e766a166935e8147fb75a7329cfebc96dec876cc45e83a8754"
},
{
"name": "raised_hands_tone4",
"unicode": "1F64C-1F3FE",
- "digest": "a2254fe75a0770708916a4ddd5db4420221c6ea9db9f74068d14eadfc0f3772c"
+ "digest": "78a8cbf6b2b85be4d6b18f0ff6a77f197963117955725fb7e57e0441effb928f"
},
{
"name": "raised_hands_tone5",
"unicode": "1F64C-1F3FF",
- "digest": "bd7c9897cefb454ccdc46027bf56d6587565bdd345d7d0f081b7b671a53f6c99"
+ "digest": "2a5ed7334a17172db0cd820a559e7f75df40ec44de6c25d194c76e1b58c634cb"
},
{
"name": "raising_hand",
"unicode": "1F64B",
- "digest": "d57178fc77e9fa140682634da35f9ab12a65d9b4c506b7cd8a9697f1b5910bdb"
+ "digest": "512750b00704f1ccefd3c757743540b785ad7670dbbe4a2c4dca8d93e6701920"
},
{
"name": "raising_hand_tone1",
"unicode": "1F64B-1F3FB",
- "digest": "f46b34361ef79743f3187d6860182bbe1ae411031db7fe5c0f7292fa472b9c16"
+ "digest": "2897722f091c273dd3714cff7423c2475bc3070416c28014ca03322b9ece48bc"
},
{
"name": "raising_hand_tone2",
"unicode": "1F64B-1F3FC",
- "digest": "20b85a2ebca150b2020a04b41d34884c78c22f42c251e2b9d23fd3724574143b"
+ "digest": "59199b334b3845911382c1f29bd7c0d5ef9d2486417345e265b166ead7d3e1c1"
},
{
"name": "raising_hand_tone3",
"unicode": "1F64B-1F3FD",
- "digest": "5e0401b528c2b8edff766d39cdcedbe9abebe4c940df7a36ace61f59c08d508a"
+ "digest": "f95b338d5efcf14ef12f415a2c1bba93df48628ddc94f34f70c31e1b3c2e1d28"
},
{
"name": "raising_hand_tone4",
"unicode": "1F64B-1F3FE",
- "digest": "e4f5624264269ad09cde207cd7d4eb0fd46de816880daeec457ac8cd51cc1b7b"
+ "digest": "951ddbfdb57d5a60551b59b3d0f7ca00a64912f4a101a73afaebd68445cd6cec"
},
{
"name": "raising_hand_tone5",
"unicode": "1F64B-1F3FF",
- "digest": "eb34b6c037bee5bbc4222f6aab421aa785f527ebf1b5e971769e5102244d60e1"
+ "digest": "9370f93704d8f89ca6dc946715eab5e7dba82bf04dd68c00f5c0abb8bc16371e"
},
{
"name": "ram",
"unicode": "1F40F",
- "digest": "b71950d7a286a4c4909c5ec7c35211c2a5c20b6bad341bd863c6a85c4bcf9c80"
+ "digest": "2875ab28e1018b39062aeb0c5ce488c48a98f13e9f2364470a0a700b126604f2"
},
{
"name": "ramen",
"unicode": "1F35C",
- "digest": "7dd185b24852b577913edc78647cd53b27d42e225fde29aa2f3aba25c980b5c4"
+ "digest": "425662a49c4c13577c0de8d45d004e5ba204aaadbaabae62a5c283ecd7a9a2c5"
},
{
"name": "rat",
"unicode": "1F400",
- "digest": "7a10d9ba5ee1010d421d9cf73d7966507302a69617a32fe9f1a00d57a31f7bd7"
+ "digest": "14380d65498c6ce037c02a93bca2b24f25a368d85278d6015b8c9f7cd261f8e2"
},
{
"name": "record_button",
"unicode": "23FA",
- "digest": "c2ba672994ad0f99d7fdc449f3fee45a2dca68a58f9fe95825b38465a30ef44e"
+ "digest": "92be12161ba206bb2e06a39131711c7b17368d55b4aae0b48f0ac5b6b1cde76b"
},
{
"name": "recycle",
"unicode": "267B",
- "digest": "74a54ed62a40dfbdcace1f08b085658a77d45c62570273927ad270bf9a8a2f4d"
+ "digest": "c377e8537367b05b5de9be860a0fcabd7aed2bf4ba146eefc423671a21530369"
},
{
"name": "red_car",
"unicode": "1F697",
- "digest": "558730d6418aa5d85b73af58c8041efd12cff906e26ea47c50963f66d33d6eb8"
+ "digest": "8a99832a195263c0e922af53d52dea37aa3e07032b3c2a1977f8527b4a144b9c"
},
{
"name": "red_circle",
@@ -8837,72 +8837,72 @@
{
"name": "registered",
"unicode": "00AE",
- "digest": "ed924107384461aabb4924c401c6c087ffa047bc2ef735823e7c2be67804707c"
+ "digest": "9661b1df529ecb752d130820c55c403e5de263748eb02f7fea327818bc282d94"
},
{
"name": "relaxed",
"unicode": "263A",
- "digest": "65072f7b9bfaaa92b8a0ed012dffe2cfd2efa3748264aaf450aa31ba6bd44045"
+ "digest": "2d5aed4fb8504c6d6660ef8d3bfe0cc053dcd6099c2f53748c202dc970c639bc"
},
{
"name": "relieved",
"unicode": "1F60C",
- "digest": "1f2c7ae6a9d74a112de89403be6eca3d8155d70395e7fce51032fc961f235c7d"
+ "digest": "b4ce2ba6c220d887fe5e333c05ed773df9b6df0ac456879fd8f5103ff68604a5"
},
{
"name": "reminder_ribbon",
"unicode": "1F397",
- "digest": "e4a2afc7dce40589657f7043ba8acc9638fd4117252278233ea89f84cddad387"
+ "digest": "c3de2a7c9350b77a0b86c0dcce9dcd9953ea8a97aa1e7aed149755924742f54d"
},
{
"name": "repeat",
"unicode": "1F501",
- "digest": "27b6dad9215e58e24c607a39dbf398ecf66ccb692c81e08eb2f5f4912db30522"
+ "digest": "b9512d508613ed0eb3181eb1030f7f6fd6b994476ecdfa308733c6df975fb99e"
},
{
"name": "repeat_one",
"unicode": "1F502",
- "digest": "052d13f2b08eaf70b31252aa78f95d06fbe22c58945c19381b13cbeb1c855651"
+ "digest": "53409cf24dd4bb0d7b50ae359f15d06b87b7f4a292ed5c3a09652fa421a90bf2"
},
{
"name": "restroom",
"unicode": "1F6BB",
- "digest": "b77fbc4247c241362e5ef9e6eb58b1b437aa9d16b65886cec0c55ceb55c1440e"
+ "digest": "2e7a1bfc9a9d49b0272230a91db7369e24d54bf1de8e683d36b85f1d8c037f77"
},
{
"name": "revolving_hearts",
"unicode": "1F49E",
- "digest": "2b8925d3e78df2dba8534252fe60bf03285346f6b3697be7668bd568e6d85931"
+ "digest": "c43d3197cb4cf06659f643638f6c4e91a2889e0f6531b7d81ea826c2a8b784fc"
},
{
"name": "rewind",
"unicode": "23EA",
- "digest": "91a95b26d12ca76111556096f4d96484c9f1d7e1b20ccff5a3291b36e529a6d1"
+ "digest": "d20c918c1e528ff0947312738501ca9a6fb6ff4016aad07db7a8125d00fd65cd"
},
{
"name": "ribbon",
"unicode": "1F380",
- "digest": "9c0296d8c2baa84c99347c431bf79b288d98b5f17b1ce7605ad7ce1da265d5aa"
+ "digest": "74315fe907f9f0203afe139cd4552aa442eecfa2a64fac12db3e1292fc5a8828"
},
{
"name": "rice",
"unicode": "1F35A",
- "digest": "e34849496a79e71ae4700df94f2a54895bf6de758a92edeae33fe78295a3ba21"
+ "digest": "f544f12606de59d28739798003f14ebd8869856add8e24496ec5dda3e131daf4"
},
{
"name": "rice_ball",
"unicode": "1F359",
- "digest": "52df5da8b0edbdeb56d66e0f30ad4549abdd81c064f7269d920dcac66a3df2e4"
+ "digest": "2cba6f5364cd366859bc8948897b65fc97b225ea7973d9be3b24aba388fed8e8"
},
{
"name": "rice_cracker",
"unicode": "1F358",
- "digest": "d55f8f9d807f4619eb243c510938067a7417a64bd9435b05dfeb2a36fdb2b6a0"
+ "digest": "ac0f805d41d4f322154c1968bd3ce3e9aabcd39d908182e52fd7d28458dbef92"
},
{
"name": "rice_scene",
"unicode": "1F391",
- "digest": "482d854d8d30edfc1ecd48a4ce476e6498606321405bf5a0b4ff74489a092af8"
+ "digest": "b942a06d3da0570aca59bab0af57cd8c16863934f12a38f70339fd0a36f675f5"
},
{
"name": "right_speaker",
@@ -8932,7 +8932,7 @@
{
"name": "ring",
"unicode": "1F48D",
- "digest": "ae2a93e7895b9b89f5a39f01d356ffed988f219ef8b658a56c55285826a4533b"
+ "digest": "b5322907222797b5e1786209cda88513e76cd397a40f0a7da24847245c95ef9d"
},
{
"name": "ringing_bell",
@@ -8942,47 +8942,47 @@
{
"name": "robot",
"unicode": "1F916",
- "digest": "cc0e363774b86e21a5b2cea7f7af85bca9e92c124ebcd39c6067c125048baa60"
+ "digest": "4d788e6ec89279588b036fca6b17f5a981291681df8f90306ecf5c039de40848"
},
{
"name": "robot_face",
"unicode": "1F916",
- "digest": "cc0e363774b86e21a5b2cea7f7af85bca9e92c124ebcd39c6067c125048baa60"
+ "digest": "4d788e6ec89279588b036fca6b17f5a981291681df8f90306ecf5c039de40848"
},
{
"name": "rocket",
"unicode": "1F680",
- "digest": "65d8bd005ceac41904237b7a8c5f55f16713a55d971522f0bbe63a1d548e515d"
+ "digest": "b82e68a95aa89a6de344d6e256fef86a848ebc91de560b043b3e1f7fd072d57d"
},
{
"name": "roller_coaster",
"unicode": "1F3A2",
- "digest": "907baab1f3d7becf3f8a3b1264642b395bd73b4af49e23058b3abb5c69e9106a"
+ "digest": "a65e9ace1d7900499777af1225995f17af90a398bb414764c20b6e09a8c23a2c"
},
{
"name": "rolling_eyes",
"unicode": "1F644",
- "digest": "f596f203030b6c9bd743848512aa3fc7919447020d35ae5c2bf13ccb16fa2dbe"
+ "digest": "23dea8100da488a05721a4e82823eb438393b0ea762211c9ecef011d127aa1b7"
},
{
"name": "face_with_rolling_eyes",
"unicode": "1F644",
- "digest": "f596f203030b6c9bd743848512aa3fc7919447020d35ae5c2bf13ccb16fa2dbe"
+ "digest": "23dea8100da488a05721a4e82823eb438393b0ea762211c9ecef011d127aa1b7"
},
{
"name": "rooster",
"unicode": "1F413",
- "digest": "6cefdaa45631ed8c9480e15f578c793d95af81b42687164fd7900eee325ccf07"
+ "digest": "2b90c5cf6fa46da13eb77285443d600afcea0c48bd1d215d60167e7dc510da5d"
},
{
"name": "rose",
"unicode": "1F339",
- "digest": "584909a4a2ece625c688f8479a39692bb8e816b692e6eb7dfd40cb045259b1b2"
+ "digest": "73799e459dba188de4de704605d824242feeb65d587c5bf9109acf528d037146"
},
{
"name": "rosette",
"unicode": "1F3F5",
- "digest": "0ce3b85ca05124ab99d57ebc9aa17bb246ee614d2fcda1ef62bf42ac7e616148"
+ "digest": "2537def4deef422d4e669b28b1a0675259306ab38601019df3ec3482b14e52d5"
},
{
"name": "rosette_black",
@@ -8992,542 +8992,542 @@
{
"name": "rotating_light",
"unicode": "1F6A8",
- "digest": "369e069e0bfecc7413e75f4015e9c1de527a33c7cce3f6c2b4adb60a0d9d338c"
+ "digest": "91fcdb85a752ae904d335a978c7e7936aed4c75d414b35219b5a74430e51555f"
},
{
"name": "round_pushpin",
"unicode": "1F4CD",
- "digest": "1bc5fe5a90a6e56ea00246f1b008a0e0cce0d77c226dc0300bf9a2804b543877"
+ "digest": "8ffca77bbdc6f1f726daf3abd6eff338a5ad1aa9b09dbbd8782c1e7ef5452f30"
},
{
"name": "rowboat",
"unicode": "1F6A3",
- "digest": "c10e09bf8be8b1a8ef3113edd9327126d6a4644f3bc81c7ada2922851e4d1cfb"
+ "digest": "83715d83a061926d4ad3bb569b21f5d337e3ebd4c9bcdfe493e661c12adc0a16"
},
{
"name": "rowboat_tone1",
"unicode": "1F6A3-1F3FB",
- "digest": "a84fc1b30d1a284dcd3899dc4de8f11e7b65c258528eb41c7dbf8f82425fee12"
+ "digest": "e279ac816442c0876fba1f42c700b80f2fb6de671e1a8a9e9d11b71eed5c58e8"
},
{
"name": "rowboat_tone2",
"unicode": "1F6A3-1F3FC",
- "digest": "85f001430a2ad607a15901f7c2dcf8381471f42d6cc0775e76a2ff1f457151c1"
+ "digest": "6a48eba352ed4971d26498b6c622e5772389c89c5205ed02acde8e995dddcc3b"
},
{
"name": "rowboat_tone3",
"unicode": "1F6A3-1F3FD",
- "digest": "adf8b1e45a46a13f3db40c29df0312216558e9d0c615aa46a8e913cee5003a81"
+ "digest": "875948f6d8354ebd95ce9a66fde30f06a8366dcd89d5ca3e660845f8801e9305"
},
{
"name": "rowboat_tone4",
"unicode": "1F6A3-1F3FE",
- "digest": "05482749ec40bdf02e53fc42d316c51f4f3ed643f21e8fc16b81930e4a884bda"
+ "digest": "8c7ac7346b0020d0ff5e2f4a1efb1b7785eac637f17556663ec33e2335083f0a"
},
{
"name": "rowboat_tone5",
"unicode": "1F6A3-1F3FF",
- "digest": "d4bb337d948996d4a23d87f99988f02fc207815b862082ffd2eef5f0c1016aa9"
+ "digest": "a399dbb647892b22323e0bf17bc36a9b5f1708ebedf9ba525233ee7b9d48339a"
},
{
"name": "rugby_football",
"unicode": "1F3C9",
- "digest": "e14aebbded78d4a5e9b4028f79a8ca840d02798c6758cb9e926e992e2a35a4f3"
+ "digest": "cc6f00ade3e0bbb7899e7bfb138b57216dd66de26d7967d5ffa501f382ed09f4"
},
{
"name": "runner",
"unicode": "1F3C3",
- "digest": "58a884f06d37b0ce78197bebcd3f0e102dd90022ebd86ec70a2ef5a5cdf9683b"
+ "digest": "e9af7b591be60ade2049dbada0f062ba2d3e17f02bec76cbd34ce68854a2a10c"
},
{
"name": "runner_tone1",
"unicode": "1F3C3-1F3FB",
- "digest": "65f1633d1517803de23686d2dbcc75a5787874266db4981138ccdbe4badc773c"
+ "digest": "21091cbb09c558712ecf63548bf28b7995df42bdb85235088799a517800e52f5"
},
{
"name": "runner_tone2",
"unicode": "1F3C3-1F3FC",
- "digest": "2bc81f3fb77445cdc75c34806ab0ce912bacfe47f63b5d2011a4f5d370cf7064"
+ "digest": "1fe3d194f675a46fe67799394192e66c407dd81163363692c5e7da32ddb9af2b"
},
{
"name": "runner_tone3",
"unicode": "1F3C3-1F3FD",
- "digest": "beaf5f254cba2991fdd0c38ce2ddd1b4c1110e15b2b7bc026d32f162e295c4ef"
+ "digest": "8cea1bf4ef3be71f42dc5bae978d5b7a197a3851543225349ef0dda29a370537"
},
{
"name": "runner_tone4",
"unicode": "1F3C3-1F3FE",
- "digest": "21d531ba9b3d13747ad636b8f7a6f184c974bf61d9f529975a64f9629263c407"
+ "digest": "c33f0b8b5a71d295fb6ba322e79446964a8eca9e4573efd591e4273808b088a0"
},
{
"name": "runner_tone5",
"unicode": "1F3C3-1F3FF",
- "digest": "b02a5bcc58cc45f8219262ec44c77764172fd8f2624d9122ded4a5a5db04c0ed"
+ "digest": "9f59e6dd0fdf2f17bceb41f5c355b4e6f3c8bb8cbd8af0992f0b5630ff8892e8"
},
{
"name": "running_shirt_with_sash",
"unicode": "1F3BD",
- "digest": "431bed35f4a55175bf99af769e74a81e8650c6ab34af6ecddaa1417ff7e437e6"
+ "digest": "7542307d3595aca45e8ccae66b6e58b6e92870144b738263d5379ec6dc992b76"
},
{
"name": "sa",
"unicode": "1F202",
- "digest": "a47a480631f874e8a2cd69b5d513f90a1e81a96bfa2f6025bf244a82baca3656"
+ "digest": "6042bcabd1516ef3847d695aba22851c49421244432d256e24eba04e8a223dab"
},
{
"name": "sagittarius",
"unicode": "2650",
- "digest": "14871e6681c35e4a63a0b19613f77b3674d00cb78d06975e02ca29e61b5cea8c"
+ "digest": "a02593e025023f2e82a01c587a8c0bbb1eff88cbcabf535a1558413eb32ed1d5"
},
{
"name": "sailboat",
"unicode": "26F5",
- "digest": "6f742dde6c180a174b771aa3942b558e98a3dc1eb212dd31add86c5fa5620865"
+ "digest": "c95ef4dc939cbdcb757ef3cd90331310e8c0a426add8cc800bae2540148a3195"
},
{
"name": "sake",
"unicode": "1F376",
- "digest": "aa1392790c805950779dde7778292c937f8c1aaecb522876171d5ee542ec51f8"
+ "digest": "0a786075f3d9da48ae91afccf6ae0d097888da9509d354ee1d3cb99afcc88fe4"
},
{
"name": "sandal",
"unicode": "1F461",
- "digest": "14f1e9003a6acd90a55f23c48ed87a758fca586f2e0b0edc4dc9d1deef9eb067"
+ "digest": "03c3077cb4bd900934f9bdf921165b465e5cc9a6bee53e45a091411bceb8892d"
},
{
"name": "santa",
"unicode": "1F385",
- "digest": "12feddd84eb49ce30ae68d4f93d66e2c0dd11297a4d1275c9a50d4f35bea83a9"
+ "digest": "178513e3d815917e59958870f5885b3414b43a16b8056980c863a468dfe00179"
},
{
"name": "santa_tone1",
"unicode": "1F385-1F3FB",
- "digest": "a75813770efe27d5b4c80ad892d0c796d88d1a0dbb1bd02d5f68882d7abad479"
+ "digest": "bf900bbc19bbd329229add9326e28e8197b69d6ddceb69f42162b0200fde5d16"
},
{
"name": "santa_tone2",
"unicode": "1F385-1F3FC",
- "digest": "90f8072fdde5f4a275cbd1902d6c94689d453b1bee0336213dc9d6f7e1d038e1"
+ "digest": "7340f2171adab97198e3eecac8b0d84c4c2a41f84606301a0d10e9fe655c93d1"
},
{
"name": "santa_tone3",
"unicode": "1F385-1F3FD",
- "digest": "0973053e7b77d268080126a50b95b45429630e5d49f62210e7b71840794c7dc5"
+ "digest": "7368ab75454ec28d8f7d6baef6ad69b5278445a9f50753f6624731bffde32054"
},
{
"name": "santa_tone4",
"unicode": "1F385-1F3FE",
- "digest": "5cd49c0d199a42846b400b3c1244d448ed6fe5ce993d379817cb2a5f7c0b609b"
+ "digest": "0ee60188353e0ee7772079c192bebbc6d49e74e63906f840c66da4eb35f4f245"
},
{
"name": "santa_tone5",
"unicode": "1F385-1F3FF",
- "digest": "a54c36dfa99b39549fb1d3dd7f0021a7aee28112960172ed466dacc67961c525"
+ "digest": "e4378a0cc5d21e9b9fe6e35c32d1ebc6fb8c2e1c09554cd096aeaefd3a6eb511"
},
{
"name": "satellite",
"unicode": "1F4E1",
- "digest": "3b9797c8161526edce0bd8e9b8563055166f9307761c367ab3e2ad7645b6dee0"
+ "digest": "c9d63118dcb445856917bb080460ab695cc78e715dcbba30ba18dffa9e906b27"
},
{
"name": "satellite_orbital",
"unicode": "1F6F0",
- "digest": "104b135e3736a4bcfd51a42dadb53bf3e00d7f85d77a94bcb86c6704fbfacd01"
+ "digest": "beb2f50e7f2b010e76bed9daa95d7329a93c783d3ebc4f0b797dd721c5e3d32d"
},
{
"name": "saxophone",
"unicode": "1F3B7",
- "digest": "1090da174ce8aa4f7d35025f65d5ac235e09310abde998d2a725ef3a989a2b75"
+ "digest": "dfd138634f6702a3b89b5a2a50016720eef3f800b0d1d8c9fe097808c9491e96"
},
{
"name": "scales",
"unicode": "2696",
- "digest": "b2984caa182b691a33650344708f47c61d6d319fd067760d7594c2ef60c1e27b"
+ "digest": "2280c026f16c6b92e0daa00bc14e718770f8d231c571ab439bde84d837cf31cc"
},
{
"name": "school",
"unicode": "1F3EB",
- "digest": "caf35260dc465a833521e4a0034201978fed41bbf72cd770756b3340c60e8a0c"
+ "digest": "af198b068a86ccad3daec4c6873e6b4735086c1ecbb3848182e70bae9aa3ee24"
},
{
"name": "school_satchel",
"unicode": "1F392",
- "digest": "a89a2cc46d24d57c2d6b95ed7a56ed829ae2f97b9e6201b2d5adc78c2b78518b"
+ "digest": "f670ae8aea67eb9d8aaa0bf2748c1cc3e503dcc1dbe999133afcdf21af046b24"
},
{
"name": "scissors",
"unicode": "2702",
- "digest": "a4e91127ac83acf5ebc64fbeca768cbbf24f2f0a484861c9c8104bee377b97ae"
+ "digest": "95225be28f05d8b5a6b6e6bf58d973f61f183ad4fef55a558dc1b810796b85c8"
},
{
"name": "scorpion",
"unicode": "1F982",
- "digest": "a090a96731bc1171b054b51abec4c9b36faa62708fd51ac48277ccf5e55d9d12"
+ "digest": "d41119d1ea5daf727c17dbea7dadec1718c72fc9f98ae88252161df5fde0938a"
},
{
"name": "scorpius",
"unicode": "264F",
- "digest": "1ad9bc1030a8f58f3f3223bac52c954cc7a0350805a9df7a42a26972c3b74728"
+ "digest": "a36404b408814c2ecb8fa8b61f5c5432dfcf54cae8c09cc67b8d0fadf7cbdc03"
},
{
"name": "scream",
"unicode": "1F631",
- "digest": "75d613786737ee9c0a74da7394b9ae190eacc7182164627ad8205ac64e4cc09a"
+ "digest": "916e4903a4b694da4b00f190f872a4e100e7736b7a2e6171fa1636f46bf646e6"
},
{
"name": "scream_cat",
"unicode": "1F640",
- "digest": "eee04ff27c2c6b57d698cb87b0af8064ba8313ffc13aa090e38cd5aa8c3d2f76"
+ "digest": "f1d3a6ff538064e7d5e0321bbc33aba44e8da703dc1894ef1403c0cd6d63d781"
},
{
"name": "scroll",
"unicode": "1F4DC",
- "digest": "b8205847649e3ce6b946f1d1da972ed015adde3841c62971b8169235f4b41c1f"
+ "digest": "9b2cb00860bcc2d20017cafb2ed9681b6232dc07273d489d75d53ce29e4ba3ab"
},
{
"name": "seat",
"unicode": "1F4BA",
- "digest": "054c4db0bc8939e9dd951a3f73e9ae4b3c31652784f4d304b509c2bd32f98e31"
+ "digest": "ae68d86fc2a07cae332451b23bd1ceba3f6526a6c56d8c1089777fa4632850e1"
},
{
"name": "secret",
"unicode": "3299",
- "digest": "77daef6e5c91d55228781ddec954a7089d1851297ec81daef6e813cd22915b5e"
+ "digest": "1d0b9adde2657f41421b135962de20820cf4b4eb0204044f9859522ab9d211b0"
},
{
"name": "see_no_evil",
"unicode": "1F648",
- "digest": "aa5883fe605aeaa172d16640b8347580f9cb7d85a596da1b13955f27b0b79297"
+ "digest": "3ff66d2e84b36d071d0a34f8e41cfd620a56b83131474ea50ed7803b635551ed"
},
{
"name": "seedling",
"unicode": "1F331",
- "digest": "a75ec929402de1e653fd6bc89e5be2f92fe5fe52f39e4b6c290eae3c59172b56"
+ "digest": "c0ec5e6d20e1afdc4e78eeddb1301c8b708ad6278e7287a4e4e825417c858e75"
},
{
"name": "seven",
"unicode": "0037-20E3",
- "digest": "c6a34020f6bb25871164fad44302a45c5bffced87f51dfbb816c2985ad7f6a1c"
+ "digest": "ae85172d2c76c44afb4e3b45d277d400abb2dc895244b9abfbd1dac1cd7c53c2"
},
{
"name": "shamrock",
"unicode": "2618",
- "digest": "530e6b987ecb9bcbf0d6e0e11bd075e7949873c784da4f9e1e1b47efd37e5058"
+ "digest": "68ed70c26e04a818439a1742d2da6bc169edd02db86b6e6f8014b651f3235488"
},
{
"name": "shaved_ice",
"unicode": "1F367",
- "digest": "fc22c3568f6be56771e83fd0e67b7eb3750041304d5d4979d3ec417f5201230e"
+ "digest": "54048e77268b7548d03088517bf8558d11324db901ca57f9bec93f1873663a74"
},
{
"name": "sheep",
"unicode": "1F411",
- "digest": "3e3656b82784164ca02c5d775db7245260f0119d2c1d35ba552a6dc75ef02544"
+ "digest": "c867c8e6e51768f1f51f4fe5abd3fbd5c1d69b01a3cb48b5fb94b6e2338a271c"
},
{
"name": "shell",
"unicode": "1F41A",
- "digest": "ff2f4f574b61bffd85c63bc2315c80d3cbcaba37a7c15a1f00783d312bd441d4"
+ "digest": "8983652d33ad6ab91195518cecb5a268a1c0ae603d271f0ddd756ff50058ddb3"
},
{
"name": "shield",
"unicode": "1F6E1",
- "digest": "062aec4a325da7b637c5710846c7e7319229be49b7e59f50428442a7ef725d60"
+ "digest": "763d0a56a62c51c730ccb0fbea38ab597cbf41a85ab968198e6ec35630d50aa5"
},
{
"name": "shinto_shrine",
"unicode": "26E9",
- "digest": "9768fe94142a7dc169703d3707b203f285a546455e29fe2bbf185d44f160d6d0"
+ "digest": "38a6d756c5aa9703510afa5076d75192f7814bbb6632394d4b8253d9ceda7f8c"
},
{
"name": "ship",
"unicode": "1F6A2",
- "digest": "f8d5b0c8ec66287b732d9171ac1913be02efb656de11501213a207d8a6c801e1"
+ "digest": "79c680845892a3e81ec6af2160ee07c29147155943e5daba6c76d04252014c20"
},
{
"name": "shirt",
"unicode": "1F455",
- "digest": "e2e72c323f3bfaea02e8cf52201aa144dc56ec0f25ec97d5f04ee6c2ee99104e"
+ "digest": "46c7253e15d7cac03699ddb1550fbb7565bbe487310f7e218c0583aa69f9d3c5"
},
{
"name": "shopping_bags",
"unicode": "1F6CD",
- "digest": "0194ba540c47e4fc6403be2df68f785d56810efc2dc011dfbf700f3778cb704a"
+ "digest": "95a3f03c675207bb1354270d02a630c204455c47b3edca23c48523a40cf3ea3b"
},
{
"name": "shower",
"unicode": "1F6BF",
- "digest": "c945120182392510348de9a957c2b77a4645d118691298a2ad660dafa62a859c"
+ "digest": "6b3c767c0eb472d4861c6c3cc2735a5e2c09681872ef42a11dc89f3c80b9da01"
},
{
"name": "signal_strength",
"unicode": "1F4F6",
- "digest": "7876ed9d602e1be746ca0629f072d85668d1f9715e9135745e803bdf89819a3c"
+ "digest": "2c6f04ba4ecd2d2d423e19eb52cfbfd253f4db6e0908d91c1af4ea6192597447"
},
{
"name": "six",
"unicode": "0036-20E3",
- "digest": "b409f23b73e46393c7a814442816b5880c38ef12a7feb5505e71276c195e8ca9"
+ "digest": "cede9324261208d0fd5d00fcdfc0df0331944bd9cff4f40b30a582a641526c1c"
},
{
"name": "six_pointed_star",
"unicode": "1F52F",
- "digest": "4bc294dcbf4185250873b52b2fb5453fb7d80df912db929add6e4b7efc066363"
+ "digest": "9203e3b4f08af439ae0bfb6a7b29a02dceb027b6c2dc5463b524dfd314cbff4e"
},
{
"name": "ski",
"unicode": "1F3BF",
- "digest": "7ee81a2e2f7ff4e32dbf3d64b034e7542ec0c86d32e25eb125052e674943d75f"
+ "digest": "80f0ca8660ba373fef823af9e98e148c4ddb1e217eb6d0a0ea2bae2288b57570"
},
{
"name": "skier",
"unicode": "26F7",
- "digest": "49df9a4206ae0c7c2dbfc8a8b13fd3e14e6f7e750bd5a8581ab6a1626d4c165e"
+ "digest": "4fff0aa155367f551a59aed9657b8afa159173882b25db9cd8434293d1eed76d"
},
{
"name": "skull",
"unicode": "1F480",
- "digest": "dfd169764b192ac7c6e5101277dd9f1e010e86bdd32ad37e00ed4499fc0a5dd6"
+ "digest": "cdd2031164281bf2b0083df4479651d96bc16d11e44bac4deaf402a9c0d6f40a"
},
{
"name": "skeleton",
"unicode": "1F480",
- "digest": "dfd169764b192ac7c6e5101277dd9f1e010e86bdd32ad37e00ed4499fc0a5dd6"
+ "digest": "cdd2031164281bf2b0083df4479651d96bc16d11e44bac4deaf402a9c0d6f40a"
},
{
"name": "skull_crossbones",
"unicode": "2620",
- "digest": "e2acf0f36b6a6800c1829a1c6551b5d0eb6dcdef4b7f02070cf69570aeab608c"
+ "digest": "ae764ba21a1fcc4409f4cc9e75a261d70b87548f64158dbd3451374ad5724123"
},
{
"name": "skull_and_crossbones",
"unicode": "2620",
- "digest": "e2acf0f36b6a6800c1829a1c6551b5d0eb6dcdef4b7f02070cf69570aeab608c"
+ "digest": "ae764ba21a1fcc4409f4cc9e75a261d70b87548f64158dbd3451374ad5724123"
},
{
"name": "sleeping",
"unicode": "1F634",
- "digest": "4ead95079b1a542eedd0e5a0e93fddb318a002bdaffaa2fe5d8d7f20bf8143ed"
+ "digest": "1050a011509b56735c9f30a6fccc876256e2a4546dc6052e518151c8aca4b526"
},
{
"name": "sleeping_accommodation",
"unicode": "1F6CC",
- "digest": "10ee8cd925a75d7977b7cf004e08b5a8147b509ee4281e879a8b57c4a7c2cb04"
+ "digest": "2ce42c027d1d0947abc403c359fd668a7bc44f5ead2582e97f3db7dd4e22e5d5"
},
{
"name": "sleepy",
"unicode": "1F62A",
- "digest": "dea3b246bb8af1b28e200358e3d5d59c8bba1813f35a7f4a57ec568ef43591db"
+ "digest": "2ee9bb1f72ef99e0e33095ec2bbf7a58ffea0ff7d40b840f4cdba57be9de74b0"
},
{
"name": "slight_frown",
"unicode": "1F641",
- "digest": "3ae82b38b58ffa50eddebd87153428d880ca181f4f4178a9ca3bd813ea15ccbc"
+ "digest": "d71d564a6c2d366a8e28a78ef4e07d387a77037fe8c99aa0ea1571299dc490c9"
},
{
"name": "slightly_frowning_face",
"unicode": "1F641",
- "digest": "3ae82b38b58ffa50eddebd87153428d880ca181f4f4178a9ca3bd813ea15ccbc"
+ "digest": "d71d564a6c2d366a8e28a78ef4e07d387a77037fe8c99aa0ea1571299dc490c9"
},
{
"name": "slight_smile",
"unicode": "1F642",
- "digest": "5eee09f634a4e2031927d008a6530a258a00e611ead0c386dd5b7ebb5e75a306"
+ "digest": "10f4b66a755f5c78762a330f20d1866e4a22f3f1d495161d758d3bab8d2f36fe"
},
{
"name": "slightly_smiling_face",
"unicode": "1F642",
- "digest": "5eee09f634a4e2031927d008a6530a258a00e611ead0c386dd5b7ebb5e75a306"
+ "digest": "10f4b66a755f5c78762a330f20d1866e4a22f3f1d495161d758d3bab8d2f36fe"
},
{
"name": "slot_machine",
"unicode": "1F3B0",
- "digest": "9d516b389299431b608c89d3f02ac68d28cb8df2a780f2048923bbcfbb49f416"
+ "digest": "914184788f8cd865cd074dca25c22acee31f5498117bd9a6e78cae67e6601652"
},
{
"name": "small_blue_diamond",
"unicode": "1F539",
- "digest": "97389e82755dc43015089dee635072357ec347f0117b2d3e9b006c46514948ee"
+ "digest": "0b56d8e6b5ddf1f49fcc76e45e5fb2ee9f99ae6ffe682c26eaea4d9b7faac36c"
},
{
"name": "small_orange_diamond",
"unicode": "1F538",
- "digest": "67442d3b707501b7768f606115688373d13617ecf0b3b03ace0f1a6d38f66ddf"
+ "digest": "a2235830550e289c1608f2dcf5ede48f5c1a0eff45570699c39708c9677ab950"
},
{
"name": "small_red_triangle",
"unicode": "1F53A",
- "digest": "e0a556a3dd5bbf0290ed7c00eb6f6307dc2ea98d1fb3111fd85a7f46242a3638"
+ "digest": "8c2985c4e9ce42d2f3b35539b879bc36206c5ef749f39fbd1eac51bd2676e1e5"
},
{
"name": "small_red_triangle_down",
"unicode": "1F53B",
- "digest": "7a11dcb8a517df220493d471759e4f4bca0db3769e2d942bbf596a88a3e57f72"
+ "digest": "46bd328df2fbf5d0597596bbf00d2d5f6e0c65bcb8f3fb325df8ba0c25e445b5"
},
{
"name": "smile",
"unicode": "1F604",
- "digest": "46a7c3545b0038dfce6825d97544f6665f28512ad05c404d668e32ac599c7ecb"
+ "digest": "14905c372d5bf7719bd727c9efae31a03291acec79801652a23710c6848c5d14"
},
{
"name": "smile_cat",
"unicode": "1F638",
- "digest": "c1db961f0fa261532b842816aca7ea7f6d8b461c7e930a1a1c91f96efd9db515"
+ "digest": "c35b76d6df100edb4022d762f47abfeb9f5e70886960c1d25908bd5d57ccb47e"
},
{
"name": "smiley",
"unicode": "1F603",
- "digest": "deeaaee64ebdd9fc0bcb719db75c3f7e0c33ddbcc97f6cd51f9f84377a4368ce"
+ "digest": "a89f31eb9d814636852517a7f4eadec59195e2ac2cc9f8d124f1a1cc0f775b4a"
},
{
"name": "smiley_cat",
"unicode": "1F63A",
- "digest": "85ad852cb3881c4b754af172fdfc6231af42578033ea9f2981ceae944c41e72f"
+ "digest": "3e66a113c5e3e73fb94be29084cb27986b6bdb0e78ab44785bf2a35a550e71bf"
},
{
"name": "smiling_imp",
"unicode": "1F608",
- "digest": "e777bdf186d89921df106d23bf002967b69afffd7e981b3cbb19f89630a06e87"
+ "digest": "3e02131d16525938f6facc7e097365dec7e13c8a0049a3be35fc29c80cc291b3"
},
{
"name": "smirk",
"unicode": "1F60F",
- "digest": "2e7fddd8bed33ef4b7d8c13320302b87a28203e576ef87bd43716952cf0b5ace"
+ "digest": "3c180d46f5574d6fca3bb68eb02517da60b7008843cb3e90f2f9620d0c8ee943"
},
{
"name": "smirk_cat",
"unicode": "1F63C",
- "digest": "9ca0721f4c18592b4b809ade8f716b95fa30cd31dd87d1e41db29a319becd705"
+ "digest": "0683c7f73e1f65984e91313607d7cca21d99acd4b2e9932f00e0fffd0ce90742"
},
{
"name": "smoking",
"unicode": "1F6AC",
- "digest": "3d14b3f0c57eb7a6a31ff371b0a454986533b79dbbeac78a76e4063478911b8d"
+ "digest": "baa9cb444bf0fe5c74358f981b19bc9e5c0415ced7f042baf93642282476ea61"
},
{
"name": "snail",
"unicode": "1F40C",
- "digest": "57d946c7ec84dfad71bc4f7a042927ec5712aef50c66d21af892b6c8a7faf5e1"
+ "digest": "5733bf3672ae4b2b3e090fa670aeac70dcbcc04ca5b13abc8c8e53b8b3d4ff33"
},
{
"name": "snake",
"unicode": "1F40D",
- "digest": "d084da540162288721364992f3b8059cbf2efd9f5b48f49a196ddbe23a073870"
+ "digest": "18da2d97c771149ef5454dd23470e900903a62ab93f9e2ce301aad5a8181d773"
},
{
"name": "snowboarder",
"unicode": "1F3C2",
- "digest": "de9e1767526de606f4908743af94cc17e89fdb0a2a44167d3d021ef09d033ab9"
+ "digest": "c6e074139b851aa53b1ba6464d84da14b3da7412fc44c6c196a8469d76915c19"
},
{
"name": "snowflake",
"unicode": "2744",
- "digest": "e476863ccd7d7b549c6191fb25c121c6a467b4baef4683b7dc3e0a793c2e5d76"
+ "digest": "6556c918e181df01ba849e76c43972d5310439971e5d8fc2409d112c05bf0028"
},
{
"name": "snowman",
"unicode": "26C4",
- "digest": "792946b8446f2243d11b89d07c73a774be3abd36573f3918640b1ba8714270b5"
+ "digest": "6137456b2335e88e09c1859615eb22bb636355ef438f7a3949ad2f3d54478dd3"
},
{
"name": "snowman2",
"unicode": "2603",
- "digest": "571acabaa4d55782c4529b762423a7e34cb1fb6bb7852cbd013e2e846d8311d1"
+ "digest": "33ec75c22a13c81fa3c6b24a77ac1a08dc0dbe70b3716cf17b6702014d8a63fe"
},
{
"name": "sob",
"unicode": "1F62D",
- "digest": "562f02ab584bcbcf9ba73cf7fa7d7129965266abd28db2c73913b8c42f2f5aca"
+ "digest": "d1ed4b31861f9f9fd4e9c95a9c17530e2320a1b4cad6ececb1545ce25d65e4ce"
},
{
"name": "soccer",
"unicode": "26BD",
- "digest": "5fd0d534659b63dc862c65a80561b255bece0b76708fe8ecbae8e01b08d8cad0"
+ "digest": "6a3f2e6a9a0b64c3fbf8705995792091daf386a4112dba75507a1f556f662f84"
},
{
"name": "soon",
"unicode": "1F51C",
- "digest": "d2a1ab16a4056d80c827ea23f9332bb73235fc841b857cbf545062ff8aeed81d"
+ "digest": "a49d1bcfbac3e6ccc05b9a9863eff74b0eb8b4d4b22b8b0f7b2787fcba1c73cc"
},
{
"name": "sos",
"unicode": "1F198",
- "digest": "fadfe8337e133a6f05d205d0807f288e5c230db04cb09f3547ce0cb73cfcf48a"
+ "digest": "2fa7e0274383aeed6019eb9177e778d7aab8b88575b078b0ffeb77cd18df14b3"
},
{
"name": "sound",
"unicode": "1F509",
- "digest": "c0074b338fd461f1f9d1143b7f9b3781ddb3fd501ea79b2410630433a8e87b83"
+ "digest": "faaca7b315b2495cbc381468580d25f1d11362441c35bb43d8a914f2ec8202d2"
},
{
"name": "space_invader",
"unicode": "1F47E",
- "digest": "d264390004bd28d664dfda0069104be6db32ce477e23a95ac595bac2e29fd4e7"
+ "digest": "e75379cb5063f9a8861d762ad1886097c1697fbb61f2e4e8f531047955a4a2dd"
},
{
"name": "spades",
"unicode": "2660",
- "digest": "d1ad99a4fc20dfea881a9062a9f2109e483dbb5dea3b29e9653cb27ec57b4800"
+ "digest": "2c4d20f6a4893cfc62498d3f1f8f67577f39ed09f3e6682d8cb9cd8f365d30da"
},
{
"name": "spaghetti",
"unicode": "1F35D",
- "digest": "ac63f9ad143e236ce6068098e5330a333ade9cddfb3dd6b1457ea47ce9dcf7e9"
+ "digest": "6d3451dc0faa1913539edb99261448f51735f269b61193c53dfe63466c0191e8"
},
{
"name": "sparkle",
"unicode": "2747",
- "digest": "95b8f4f1bb6080cd1d7bd333c4724dbba43ed196dce72a2bbaab46c4a1bc0e48"
+ "digest": "7131163cd6c2f879110c86e9f068c33cf580f7c4b619449c41851fe6083402ee"
},
{
"name": "sparkler",
"unicode": "1F387",
- "digest": "3a296e4d0081ad1a566e111d218e352e1439bba9fd04e8a1eb9a8e36bd438cb7"
+ "digest": "88539ed8a13bd66e0c265c0913bd3ec2ddc4d95484323595713beb102221a1f6"
},
{
"name": "sparkles",
"unicode": "2728",
- "digest": "5ab280ea10c30e0e0b5a26ef52b8f47ad44a983330f7ef62ac0c0888752bbdb6"
+ "digest": "cf84d16b1c0a381d5a7ae79031872747c9a6887eab6e92cc4a10a4b8600ef506"
},
{
"name": "sparkling_heart",
"unicode": "1F496",
- "digest": "f145dab6b597c07e5a851176fabaf56dd857209645483d1acc1490d12c969113"
+ "digest": "b80b1ddef83b6528b309a194f6f2faf5acab603daeb9254523efc2b941bcb6d2"
},
{
"name": "speak_no_evil",
"unicode": "1F64A",
- "digest": "6eae2d066d39c4ba81e58a8327ed875c68bc9b1297c18dc0f5243e477a81040f"
+ "digest": "d2d7cfb4d471928a496bdc146890adc8422a68500b68115630b24c125d18e81f"
},
{
"name": "speaker",
"unicode": "1F508",
- "digest": "ea59c5a9d994808ff7937c300303e644b5f1ad41097e82f9e73ea6e1c718936c"
+ "digest": "dbca5f7181728d2ad67ff76fd566ffbdf53e333e7eeed341f54668bd47969413"
},
{
"name": "speaking_head",
"unicode": "1F5E3",
- "digest": "d92cfe1200887300b2f05f9576448a2f2a79d0accd51f323a65ce3db0aa5639b"
+ "digest": "4be1af79b4506c00af4df64663413bcbae195dab0bc63c5011feb8f9663ed544"
},
{
"name": "speaking_head_in_silhouette",
"unicode": "1F5E3",
- "digest": "d92cfe1200887300b2f05f9576448a2f2a79d0accd51f323a65ce3db0aa5639b"
+ "digest": "4be1af79b4506c00af4df64663413bcbae195dab0bc63c5011feb8f9663ed544"
},
{
"name": "speech_balloon",
"unicode": "1F4AC",
- "digest": "5dccfda46fc984583bc9eaece66e7e884f2a9eb12a69dbd3493035e3c862edd0"
+ "digest": "817100d9979456e7d2f253ac22e13b7a2302dc1590566214915b003e403c53ca"
},
{
"name": "speech_left",
"unicode": "1F5E8",
- "digest": "478b0b07460a9f54b7d0050f886da59fde5e428daa11e899fc31477fda1707ed"
+ "digest": "912797107d574f5665411498b6e349dbdec69846f085b6dc356548c4155e90b0"
},
{
"name": "left_speech_bubble",
"unicode": "1F5E8",
- "digest": "478b0b07460a9f54b7d0050f886da59fde5e428daa11e899fc31477fda1707ed"
+ "digest": "912797107d574f5665411498b6e349dbdec69846f085b6dc356548c4155e90b0"
},
{
"name": "speech_right",
@@ -9562,122 +9562,122 @@
{
"name": "speedboat",
"unicode": "1F6A4",
- "digest": "553a288ab8eeb3dee7b9d1c92eba38016caef7658beaa828136ba1d6ba8ed08a"
+ "digest": "a523b2320f0b24be1e9fdbc1ff828e28d8fd9a64d51e5888ab453ef0bc9f0576"
},
{
"name": "spider",
"unicode": "1F577",
- "digest": "519f7243b5574102ce3f8953e5480812830a1feb32ae51e8573724c864338481"
+ "digest": "8411eac0c1b80926fd93cc1d6423e00b05d04c485b79ee232da8f1714e899a37"
},
{
"name": "spider_web",
"unicode": "1F578",
- "digest": "42959fae08a2162d6ee8c8706f823c5932f3801bc90da30d2ca9a48c3ff25572"
+ "digest": "2434bdfbe56dcc4a43699dd59b638af431486b52fb1d6d685451f3b231b2be23"
},
{
"name": "spy",
"unicode": "1F575",
- "digest": "eaa570a36d83119d0a596228e74affe84d7355714ff6901d88a89410d26dec2a"
+ "digest": "99fe3cdeff934726ee5855b0e401bf32570084aaad4eb10df837fd410ca742aa"
},
{
"name": "sleuth_or_spy",
"unicode": "1F575",
- "digest": "eaa570a36d83119d0a596228e74affe84d7355714ff6901d88a89410d26dec2a"
+ "digest": "99fe3cdeff934726ee5855b0e401bf32570084aaad4eb10df837fd410ca742aa"
},
{
"name": "spy_tone1",
"unicode": "1F575-1F3FB",
- "digest": "abdc066d4cad6a17047faf7806c45feb43ae1e2056cf500536f08f4173dbfa94"
+ "digest": "1720a99064061c43c7647b6bd517efa2ee2621b355a644adfb347d62849366a2"
},
{
"name": "sleuth_or_spy_tone1",
"unicode": "1F575-1F3FB",
- "digest": "abdc066d4cad6a17047faf7806c45feb43ae1e2056cf500536f08f4173dbfa94"
+ "digest": "1720a99064061c43c7647b6bd517efa2ee2621b355a644adfb347d62849366a2"
},
{
"name": "spy_tone2",
"unicode": "1F575-1F3FC",
- "digest": "72a3313ef12364105e764cc3deabd47eb6bd086f261c435682ae1cd29dc8230b"
+ "digest": "23ff0026723f2b5a46fbfb55e24c4a4a33af2bd96808b3ea3af76aae99965d68"
},
{
"name": "sleuth_or_spy_tone2",
"unicode": "1F575-1F3FC",
- "digest": "72a3313ef12364105e764cc3deabd47eb6bd086f261c435682ae1cd29dc8230b"
+ "digest": "23ff0026723f2b5a46fbfb55e24c4a4a33af2bd96808b3ea3af76aae99965d68"
},
{
"name": "spy_tone3",
"unicode": "1F575-1F3FD",
- "digest": "2a1108d3d2e778f88aa5b3ae36705c877b84d0bf6b421409582ba748aeb2aee7"
+ "digest": "1d0cb3d54fb61e4763a4f0642ef32094bdd40832be0d42799ce9ba69773616df"
},
{
"name": "sleuth_or_spy_tone3",
"unicode": "1F575-1F3FD",
- "digest": "2a1108d3d2e778f88aa5b3ae36705c877b84d0bf6b421409582ba748aeb2aee7"
+ "digest": "1d0cb3d54fb61e4763a4f0642ef32094bdd40832be0d42799ce9ba69773616df"
},
{
"name": "spy_tone4",
"unicode": "1F575-1F3FE",
- "digest": "1d4fe62912384bc0d687bcf4565752caf0ed6146c903a156d1c6ba6ea239b154"
+ "digest": "e36a4b52df6cb954fab9d9128111f1301c6d46bdeacf51993ffb5bb354cd0ad3"
},
{
"name": "sleuth_or_spy_tone4",
"unicode": "1F575-1F3FE",
- "digest": "1d4fe62912384bc0d687bcf4565752caf0ed6146c903a156d1c6ba6ea239b154"
+ "digest": "e36a4b52df6cb954fab9d9128111f1301c6d46bdeacf51993ffb5bb354cd0ad3"
},
{
"name": "spy_tone5",
"unicode": "1F575-1F3FF",
- "digest": "69c1baac73783edb9e2d0c951f922dc7dddac34d0a9c818fee8d1021bc17db0d"
+ "digest": "ffc6fefd9a537124ebf0a9ddf387414dce1291335026064644f6cf9315591129"
},
{
"name": "sleuth_or_spy_tone5",
"unicode": "1F575-1F3FF",
- "digest": "69c1baac73783edb9e2d0c951f922dc7dddac34d0a9c818fee8d1021bc17db0d"
+ "digest": "ffc6fefd9a537124ebf0a9ddf387414dce1291335026064644f6cf9315591129"
},
{
"name": "stadium",
"unicode": "1F3DF",
- "digest": "4356db5d2cdef8c40830638debaf1f50831130c12ae8d8dc3d9a6bd28fdaa1f7"
+ "digest": "73bf955e767ba1518c9c92b2ba59a2aa1ec4b018652dffd97bcd74832a33789f"
},
{
"name": "star",
"unicode": "2B50",
- "digest": "13240b8fada84e7555892996e9f9652503bf9b9a002056c2bae428d543abe2da"
+ "digest": "d78e5c1b78caed103e100150c10b08a9ca3ee30c243943d6fc3cc08f422122e9"
},
{
"name": "star2",
"unicode": "1F31F",
- "digest": "9b56c7548f6a222499d4e848576ea25eab837db72b207ebf8a62a451b35f758f"
+ "digest": "f91ac4afe3f5d4a52847ae8b4a9704b591e00399aebba553d150d7e34ee939fa"
},
{
"name": "star_and_crescent",
"unicode": "262A",
- "digest": "10b8a0771e415aa6610fa62185137aa1836c2bb3e82f1a3f601470e94f784923"
+ "digest": "1bf3d29e50034f5e7c0dccff0a3a533b74bfa9b489e357b2739a473311f1332a"
},
{
"name": "star_of_david",
"unicode": "2721",
- "digest": "5bc4d1038b8316281e01a9c575ded7ede0fc24c7593db5b5d36ca2e188aa5614"
+ "digest": "28a0bd0eeac9d0835ceb8425d72c2472464e863dd09b76a0ddc1c08cf1986402"
},
{
"name": "stars",
"unicode": "1F320",
- "digest": "23605eafc949feead3eca145a7ff5ee3b211a8bfd95621bd35dd05df532b97c6"
+ "digest": "837d9045316b8fb5e533457eac61241534f641eb78d8cb75f688f80fb8e8a7f0"
},
{
"name": "station",
"unicode": "1F689",
- "digest": "c346f12fff64161041af8492550c3541a6304e53f30288224ddd0c6fe08c4d6b"
+ "digest": "27a163ac0aea4ed247a121cae826eafc475977c68b0d888e9405bea14326ff56"
},
{
"name": "statue_of_liberty",
"unicode": "1F5FD",
- "digest": "56fa27ab059a9fd1f53aec47d9108277a3bf04a73186f36297cd1207c832ee31"
+ "digest": "f5a43599ab3f24ed3a78a745e06e2ac3e33107a292386ad81c67935ee5b22493"
},
{
"name": "steam_locomotive",
"unicode": "1F682",
- "digest": "d0ec2eb3d761ab6157e17eab1b8b4dec3a69f9becc4251592cbb67d71825e661"
+ "digest": "52ad0073f37b978faf3884fb193046f2b0614e1557bbcc9de1b020e42aff2dba"
},
{
"name": "stereo",
@@ -9692,7 +9692,7 @@
{
"name": "stew",
"unicode": "1F372",
- "digest": "12e6e4bf48a7296700e07a053d831dd67b70c308ca9522ca96e933a4d1ef6c5e"
+ "digest": "c16f61236db314ad8d9f2dd241ec1e15c8d64e5872cce93ec4d0996490dd39df"
},
{
"name": "stock_chart",
@@ -9702,212 +9702,212 @@
{
"name": "stop_button",
"unicode": "23F9",
- "digest": "57310962c7738a7da4f2a62cbd5e0b26d7aec357978267a0d8ca8e6cbd7ffb02"
+ "digest": "83f9d0da3ad845fef41b4e8336815d30e9c8f042ab2a8340894ade2f428fc98a"
},
{
"name": "stopwatch",
"unicode": "23F1",
- "digest": "c8e69c24f9da98dcb41c9c6355922d08a702f12a35667fbc5beb3f659430333d"
+ "digest": "9b6b9491a24d8ab4f896eb876da7973f028bd5e7c51a3767ba7e61bb6fbb2be0"
},
{
"name": "straight_ruler",
"unicode": "1F4CF",
- "digest": "55ff7182a3696461df52e3000708083f803bc8bf0f3c25dacb34175cc104b51d"
+ "digest": "cee31101767bd3f961363599924dc3790675d05a1285a8396428d2f91771c111"
},
{
"name": "strawberry",
"unicode": "1F353",
- "digest": "fd501e1fefb70242ac7c4dc30ad3d8c3ae200b263a832daedaa984906114afaf"
+ "digest": "5750a15e12f21259286ddbc3a8222a385b3b97a9f368897f42dd000060343174"
},
{
"name": "stuck_out_tongue",
"unicode": "1F61B",
- "digest": "1b49956cec511ee382177d95da77c8b6a9214a02c86bf7c6c6fd6cc9df3e9331"
+ "digest": "92dc42980a6dfdd7204fc874a762d6a0bbf0fdbfb5a7c0698fca04782e99fde6"
},
{
"name": "stuck_out_tongue_closed_eyes",
"unicode": "1F61D",
- "digest": "60a4d5d92550c6ad4db901d42c9f6434fe94fa3ddb353b6019a93d374d9485e9"
+ "digest": "434d25ac24cad7ba699eae876a25d9a99b584449cca50b124bf6aa7f20a83d51"
},
{
"name": "stuck_out_tongue_winking_eye",
"unicode": "1F61C",
- "digest": "d9c15ad1c4782a0391a79aeda2745127527385b0b5fc01c8d96c3f3b637a74ae"
+ "digest": "dbacd6428a2a2933212e6a4dc0c7f302177fb23b963626ccb26f27f91737f03d"
},
{
"name": "sun_with_face",
"unicode": "1F31E",
- "digest": "56b14e92f68f8701fdc42763e1f4695ed352845f22bd5d412f827e5cf98dd83b"
+ "digest": "7256ff5263006c64c03f1eb66e3ddb56d67d785d65dacc37aa886d0cd4be63be"
},
{
"name": "sunflower",
"unicode": "1F33B",
- "digest": "817dea222a75bb6492c32b4b144d07f48295d7dd113e21760f90b18277612ebb"
+ "digest": "27d1161f50f932a6b26c404cf2e8f7083683ed0f2382d62b7472acccaa6eb695"
},
{
"name": "sunglasses",
"unicode": "1F60E",
- "digest": "16003cc5256397389889f52e0a5e14daea8d8c72f2ea660b8174529868cba9cd"
+ "digest": "966684382e5c59e98319e4c0ea7c304c61c2638ad5408faa49ce2c83c4416757"
},
{
"name": "sunny",
"unicode": "2600",
- "digest": "f68a774b7d574fc711111e17368b57c40d973d263c7e857544a09051d4592ab9"
+ "digest": "460fea4cbbdd1595450c1033a2ee5de7fea2e2f147822efa49f7e204812415aa"
},
{
"name": "sunrise",
"unicode": "1F305",
- "digest": "ce06a9321bc04605538a59f9fca8536d6209d7ded03120e5d2a0be955bb17ddf"
+ "digest": "7718a49636b0cdd1862ed67c7a9d6e72f471c2591ff0d912485b1be55d1ea115"
},
{
"name": "sunrise_over_mountains",
"unicode": "1F304",
- "digest": "286244ac2bec8c5c41cf8c7c439702fa525c57fab623f7f9bd7687db0adf75b2"
+ "digest": "743d0701cdbe2a814962363813c3153d3c5e62c3e410349f56d49dbb9581f356"
},
{
"name": "surfer",
"unicode": "1F3C4",
- "digest": "d17c7ea185ca5ef5a2950ef126ee14103bf7769acb419a20d08cc023f619e459"
+ "digest": "bb440775e9213430942015c37db8de58b5a561ee971b2a0f3993fc3f1d2554d4"
},
{
"name": "surfer_tone1",
"unicode": "1F3C4-1F3FB",
- "digest": "af66f2f26071b3ba8d7c795139055a58a857212f8cb1f51a507242ad7d2c49c7"
+ "digest": "a4937b030aca30b68bb644f37cf63c38aebce3c00b57d1c8a0ffe596b57d2f1e"
},
{
"name": "surfer_tone2",
"unicode": "1F3C4-1F3FC",
- "digest": "7a34e8b1fdad0a89bbb10333d241583ef018517fdd90f171ad7121de53776a3f"
+ "digest": "1c2a954a9c5284dedf0327d6f3c954c9fdd3953b848076d298874775ad8bf0a3"
},
{
"name": "surfer_tone3",
"unicode": "1F3C4-1F3FD",
- "digest": "b2f4cbd59a0aa93c7ee2bbb14ce55c8306dc25884377982a5f132ce6c074fa1d"
+ "digest": "418a3408b9ab026124f067c8597b500217e56bc28d9844a29eea5eee6f604ff8"
},
{
"name": "surfer_tone4",
"unicode": "1F3C4-1F3FE",
- "digest": "b16a02cfcc3606524cca9408e69c654fb83a162eaec8faae8dfd8ec67fe391c5"
+ "digest": "530870b9ac9f4d45ff750e264feb90b44fb93ca2852f323987b06f5f12fb5a4d"
},
{
"name": "surfer_tone5",
"unicode": "1F3C4-1F3FF",
- "digest": "b9a156e1aa57544b703db4e4a7773e244a3139e82c2c808c2e5a804fb524f512"
+ "digest": "40e11b1ae652cfd085d083377f1da24160065ed1b67403c6fa4655e6e44169ec"
},
{
"name": "sushi",
"unicode": "1F363",
- "digest": "d2709b51ee92997c7fafa1b1517259cb896819c8dc9ba98ae26e1d44ec810d4f"
+ "digest": "b924c621236ca3284b349b0509ae1043f2fc2c7f6d67615716f9717ada78c992"
},
{
"name": "suspension_railway",
"unicode": "1F69F",
- "digest": "48903e103ef00a068b0100b28319b1e41c6a4485cb564f0ca59422ec9d3b259c"
+ "digest": "cd3d21da79864f0c018b863e82fb0561fff3c5e3c065303cfcb89c3663d638ba"
},
{
"name": "sweat",
"unicode": "1F613",
- "digest": "8d684fa882bcbf07f4e91ea02a48cd61f22e7aa206162b8352c26fc19361ed4e"
+ "digest": "1aa771479aa1ac5eeea4bafbe93ebd85a0f692f6d869034f31e25b689c2e264d"
},
{
"name": "sweat_drops",
"unicode": "1F4A6",
- "digest": "fca48e255dff08dab97ef98b75c67f7504a13be8b90afac88b69a7b7e887e445"
+ "digest": "b575b85415bc9852cf6415d417ebf799167fde03c6819ebcaa24ae1b3dde8dab"
},
{
"name": "sweat_smile",
"unicode": "1F605",
- "digest": "0c8156554eec2396b5fee908da46484945db980d2ebc6dee57b4069a86826182"
+ "digest": "171b0d0845d46c33bedb6d3b39fb1ff366e22ba90685eedabebd91bb2b0680de"
},
{
"name": "sweet_potato",
"unicode": "1F360",
- "digest": "3ce74ea9bc14906a3d29a9592c0657aee8f7961d406992752f7580b16ca6bdd0"
+ "digest": "4b91920f0b87d42763313bc476f4c821a74e4c12dc1c92165a859dddeaaf8844"
},
{
"name": "swimmer",
"unicode": "1F3CA",
- "digest": "05f3aa8544e3b15837bb06ae47344633b3e60d64c572dc6638c4cee19d6e5506"
+ "digest": "2c4ed4a51aad99d9957ae11a219d5164db9748fc3a65002c6085a9f15adfa9e2"
},
{
"name": "swimmer_tone1",
"unicode": "1F3CA-1F3FB",
- "digest": "85a266a9131f6a1b37e758305ca43ffb46e3e07b0a465c5faefbdb5e5adeb7a4"
+ "digest": "48588f129ee4af52ca2e0f4594213391978601087cd607896b2f979ca077284b"
},
{
"name": "swimmer_tone2",
"unicode": "1F3CA-1F3FC",
- "digest": "f2afdc4d05a2694e663a420d5ad82bd48c92aedc4137d0fd3725bf08c41bd12a"
+ "digest": "fff209448524bd1ef4d6decabf6c1ead94c8d3d5b1bfb5e54f20cc8e139232fc"
},
{
"name": "swimmer_tone3",
"unicode": "1F3CA-1F3FD",
- "digest": "b87ecc38fb9e8eeeef8b120164d758d3f6a68a407053b03261354fd7f90f43b6"
+ "digest": "2003932cb2cf4ae9a10b23338bf375a9293fb18c0ecf91bdfae73be6eebb3800"
},
{
"name": "swimmer_tone4",
"unicode": "1F3CA-1F3FE",
- "digest": "a08629cf3484953b851b357c6a04891fb97ac15e70c376bbb82af47479835e1c"
+ "digest": "20b4bff9baa1c694ad98067dde834c56092f023b9664bec382c2e512232bd480"
},
{
"name": "swimmer_tone5",
"unicode": "1F3CA-1F3FF",
- "digest": "21d83f66b2ef3e348f9e14ec108b9a90262d9934039ebd573471d2bdcde68974"
+ "digest": "0ff8eb57c2be8e80a1bc6ba75b8d9ffb9bd8d3be636150c4c03399ec1886f218"
},
{
"name": "symbols",
"unicode": "1F523",
- "digest": "f33c3ce58374e23b8957c759016fdb5c56ef7fe812bd4e693ae8ff7574cf6bbf"
+ "digest": "2a2a79816c4d0751a0d73586eec5e63b410653d3c85cc968906bf1fc03d89b94"
},
{
"name": "synagogue",
"unicode": "1F54D",
- "digest": "b13402c3c5793ebf924335a87a9f69befb7a6c152fc2a288261b2c2d49842eb6"
+ "digest": "98569cdd7c61528963b67b7891dfa46025c5e810cbb22ee18ddb3bd85de2da69"
},
{
"name": "syringe",
"unicode": "1F489",
- "digest": "39e5e7530255ccf2ff35ec5c653568c8645a4711170c573117f796ea3438c44a"
+ "digest": "e1538e645ccc571227c994b71b3d1be2c4d072d8bd9c944a42ff4a11c91a34a6"
},
{
"name": "taco",
"unicode": "1F32E",
- "digest": "6b004ce7129e00abcc10278bba1b9c3d5ac71888b99bf353f9878d8e494e3e0d"
+ "digest": "e1e45aefdb7445faeae75c3831df6a3d6f2590fcdd48a20d847593c246df613b"
},
{
"name": "tada",
"unicode": "1F389",
- "digest": "956a180a1f18e3a1252761e5b3713324f63975ee1fe32168b59b60aa4dd8b72b"
+ "digest": "1d2e6cbb2a3244240bc70209715d2213d1efee2e370cccfbcc046c333ae2d650"
},
{
"name": "tanabata_tree",
"unicode": "1F38B",
- "digest": "d074457ba347687bfc8397ec62edee6325c411356216e7d43acd3f60628a0bb8"
+ "digest": "592f2907ffc1b914390e1a106c15120ff3607e99192158b94d237975647c5540"
},
{
"name": "tangerine",
"unicode": "1F34A",
- "digest": "1b46bb690458914220cba18c43d7ae0f6914adfee6dba7cf2bb58ed4e1854ad8"
+ "digest": "40c9ddcde1b0bcfaeb466629a87825eb8c2037835720cbee5e2fda04be3c8d0a"
},
{
"name": "taurus",
"unicode": "2649",
- "digest": "ea87fb3baa32605107d63b60847e4873ad9e21b7e7b652e3721cde777168670d"
+ "digest": "21cf24cb6410ab6596e2df8b3e242cc07f9dbb247eabc00c590fe184b373d068"
},
{
"name": "taxi",
"unicode": "1F695",
- "digest": "f44249c643a96d924e1eb35f67a133f3ca61128e610a880afaa09a73c7bcaf9d"
+ "digest": "c546cc743831cfbf0c15452767cf2a4faf3775066797e997ae7c1fcbe4eca479"
},
{
"name": "tea",
"unicode": "1F375",
- "digest": "56ab8c291de8320c5b339e1cfbe972696e4ea31c592cefa240eda9a3abdf4fa3"
+ "digest": "00e3f1e389fa58c4fcd8c53ebbf83d25872f4315845ab1984b35410ae65553d9"
},
{
"name": "telephone",
"unicode": "260E",
- "digest": "609104588e00039199a2fef3190ee6a7be5fca7cb09b36ffe5a7d800aac69d8d"
+ "digest": "3a53851e641f8ad938ce3597b1afca2ea63c9314ff81f62563b99937496a13d7"
},
{
"name": "telephone_black",
@@ -9922,7 +9922,7 @@
{
"name": "telephone_receiver",
"unicode": "1F4DE",
- "digest": "e3bf6034de6cf2160893ba4990eba198185a6a3f9cd5767a63b048e41c297640"
+ "digest": "1614d67f3d8814b0d75f39d55f9149e4d28ef57b343498625e62fcfff8365046"
},
{
"name": "telephone_white",
@@ -9937,52 +9937,52 @@
{
"name": "telescope",
"unicode": "1F52D",
- "digest": "abe0aca5f2c78105b0e9e4c8ee7a40adcd9bb013e7c49d568076459bade73556"
+ "digest": "4adf40387870276c4f59fb050d441023e8dac784365b6a8c0282fb519780b495"
},
{
"name": "ten",
"unicode": "1F51F",
- "digest": "7593aa7ffe7192a2e35c6ccec76522f6243777783c9152c7c03419835ea58c03"
+ "digest": "c7c9491021740d2c17edddb856f79579b0b943d8dc85a2f48dbaac84f35b8a40"
},
{
"name": "tennis",
"unicode": "1F3BE",
- "digest": "0a5fad3f7f35da0f37761e2279c148dbe154fa14c0e2a0749209b8b2b213a388"
+ "digest": "dc1600b4d8dce3d26259eb0d1c6ab042566565e3c1f2c96112210f1550a716fd"
},
{
"name": "tent",
"unicode": "26FA",
- "digest": "7ddf437d8d186e4e3c3e818d137518d590fa06098813c7fe20e1f2a9704feab2"
+ "digest": "30d9b17ac3219d4970ddf54d7c1a288b0ae50f7f3b82ed232c0b1b19ef585662"
},
{
"name": "thermometer",
"unicode": "1F321",
- "digest": "597d1714442698a22187fee4d57a2580322f7206c7d51e4519023824598ec08f"
+ "digest": "66616babbcaef256d7b652796c760e8e893cb950c073348a408fe70904f80f25"
},
{
"name": "thermometer_face",
"unicode": "1F912",
- "digest": "f19c489d89dd2d39770a6c8725a20f3e98f9e5216774af60c0665fd6a03a7687"
+ "digest": "ac2b5caddd128563711a9dcc7f690cf210f684d5e8b64b09c0431d6902437126"
},
{
"name": "face_with_thermometer",
"unicode": "1F912",
- "digest": "f19c489d89dd2d39770a6c8725a20f3e98f9e5216774af60c0665fd6a03a7687"
+ "digest": "ac2b5caddd128563711a9dcc7f690cf210f684d5e8b64b09c0431d6902437126"
},
{
"name": "thinking",
"unicode": "1F914",
- "digest": "f64a9a18dca4c502b46f933838753a818b604a9d0268aa32eda26cbd31abc58c"
+ "digest": "4f0b84e5ab8a650cafb166e93688f0e9b31b9ade22a91035261ac90490edb9d3"
},
{
"name": "thinking_face",
"unicode": "1F914",
- "digest": "f64a9a18dca4c502b46f933838753a818b604a9d0268aa32eda26cbd31abc58c"
+ "digest": "4f0b84e5ab8a650cafb166e93688f0e9b31b9ade22a91035261ac90490edb9d3"
},
{
"name": "thought_balloon",
"unicode": "1F4AD",
- "digest": "76c8513191641f0a79e878ccc0d83c4576984609810633f596db2f64cc684b7d"
+ "digest": "bf59624560c333561d636aedf2c8827089e275895cf434974daaabb3d5cea46e"
},
{
"name": "thought_left",
@@ -10007,7 +10007,7 @@
{
"name": "three",
"unicode": "0033-20E3",
- "digest": "ca0147a8f67cea3bc2516fa8deef4325188359559786c94ff0b27f90eef04b88"
+ "digest": "d3f85828787799c769655c38a519cad0743ab799ab276c7606e6e6894cc442e6"
},
{
"name": "thumbs_down_reverse",
@@ -10032,192 +10032,192 @@
{
"name": "thumbsdown",
"unicode": "1F44E",
- "digest": "a98f742c9773e0d95c0de5e1c10d1ab373fa761378a205f27d095e85debe69a3"
+ "digest": "5954334e2dae5357312b3d629f10a496c728029e02216f8c8b887f9b51561c61"
},
{
"name": "-1",
"unicode": "1F44E",
- "digest": "a98f742c9773e0d95c0de5e1c10d1ab373fa761378a205f27d095e85debe69a3"
+ "digest": "5954334e2dae5357312b3d629f10a496c728029e02216f8c8b887f9b51561c61"
},
{
"name": "thumbsdown_tone1",
"unicode": "1F44E-1F3FB",
- "digest": "5d0a7c63d52eafe6267c552168c5557a66622009d565c3cf7b5378c1f6e84bce"
+ "digest": "3c2853491473fd7ae2d1b5415a425cc390d26a8754446f8736c1360e4cb18ba3"
},
{
"name": "-1_tone1",
"unicode": "1F44E-1F3FB",
- "digest": "5d0a7c63d52eafe6267c552168c5557a66622009d565c3cf7b5378c1f6e84bce"
+ "digest": "3c2853491473fd7ae2d1b5415a425cc390d26a8754446f8736c1360e4cb18ba3"
},
{
"name": "thumbsdown_tone2",
"unicode": "1F44E-1F3FC",
- "digest": "ca5c15dc516660b2989a1c717bf3745fdfb6964c7acf3b938285ff6c7caf2ca2"
+ "digest": "4e0f8f86a06b69e423df8d93f41ec393f12800633acc82c4cb6dff64ca0d8507"
},
{
"name": "-1_tone2",
"unicode": "1F44E-1F3FC",
- "digest": "ca5c15dc516660b2989a1c717bf3745fdfb6964c7acf3b938285ff6c7caf2ca2"
+ "digest": "4e0f8f86a06b69e423df8d93f41ec393f12800633acc82c4cb6dff64ca0d8507"
},
{
"name": "thumbsdown_tone3",
"unicode": "1F44E-1F3FD",
- "digest": "05740e3568795270674dac9134198bf75b1b778c11daa71649c88c231859ec16"
+ "digest": "e08fa35575f59978612d4330bbc35313eca9c4dfa04f4212626abc700819effe"
},
{
"name": "-1_tone3",
"unicode": "1F44E-1F3FD",
- "digest": "05740e3568795270674dac9134198bf75b1b778c11daa71649c88c231859ec16"
+ "digest": "e08fa35575f59978612d4330bbc35313eca9c4dfa04f4212626abc700819effe"
},
{
"name": "thumbsdown_tone4",
"unicode": "1F44E-1F3FE",
- "digest": "5ee93bcc2f515806462a7b303064beade2b22a3f43a8162e39fd65d15d772e27"
+ "digest": "7c6d118d20d5add8ca003e4a53e42685a1f9436b872ed10d79f67ad418fb2a44"
},
{
"name": "-1_tone4",
"unicode": "1F44E-1F3FE",
- "digest": "5ee93bcc2f515806462a7b303064beade2b22a3f43a8162e39fd65d15d772e27"
+ "digest": "7c6d118d20d5add8ca003e4a53e42685a1f9436b872ed10d79f67ad418fb2a44"
},
{
"name": "thumbsdown_tone5",
"unicode": "1F44E-1F3FF",
- "digest": "5c9ef8d53cf6f755668ab6dabfbfcdfd4b95fd59db3b3dd60290efefe9c33994"
+ "digest": "8697c4a4ee4d6669dc2d47aa97699c42012ca59b80818ad6845878b37b4a9c58"
},
{
"name": "-1_tone5",
"unicode": "1F44E-1F3FF",
- "digest": "5c9ef8d53cf6f755668ab6dabfbfcdfd4b95fd59db3b3dd60290efefe9c33994"
+ "digest": "8697c4a4ee4d6669dc2d47aa97699c42012ca59b80818ad6845878b37b4a9c58"
},
{
"name": "thumbsup",
"unicode": "1F44D",
- "digest": "28b31df963773ba42a1a089f43cd89d0ce1ab0981e5410f41242e9a125fc1aee"
+ "digest": "59ec2457ab33e8897261d01a495f6cf5c668d0004807dc541c3b1be5294b1e61"
},
{
"name": "+1",
"unicode": "1F44D",
- "digest": "28b31df963773ba42a1a089f43cd89d0ce1ab0981e5410f41242e9a125fc1aee"
+ "digest": "59ec2457ab33e8897261d01a495f6cf5c668d0004807dc541c3b1be5294b1e61"
},
{
"name": "thumbsup_tone1",
"unicode": "1F44D-1F3FB",
- "digest": "f6365942738d2128b6959d6672b3d295757dc8240703cb84a2b014ad78d67de3"
+ "digest": "f57e6c525e8830779ea5026590eec3ca10869dc438a0c779734b617d04f28d21"
},
{
"name": "+1_tone1",
"unicode": "1F44D-1F3FB",
- "digest": "f6365942738d2128b6959d6672b3d295757dc8240703cb84a2b014ad78d67de3"
+ "digest": "f57e6c525e8830779ea5026590eec3ca10869dc438a0c779734b617d04f28d21"
},
{
"name": "thumbsup_tone2",
"unicode": "1F44D-1F3FC",
- "digest": "771d30146e4dc947a69057b05d32c765c8457ab02b5342889c5489acf27ef356"
+ "digest": "980eeeb1d8f5d79dae35c7ff81a576e980aa13a440d07b10e32e98ed34cbf7f1"
},
{
"name": "+1_tone2",
"unicode": "1F44D-1F3FC",
- "digest": "771d30146e4dc947a69057b05d32c765c8457ab02b5342889c5489acf27ef356"
+ "digest": "980eeeb1d8f5d79dae35c7ff81a576e980aa13a440d07b10e32e98ed34cbf7f1"
},
{
"name": "thumbsup_tone3",
"unicode": "1F44D-1F3FD",
- "digest": "0bb7bbfb654c6139260e1786e7ffa5a33f31e19410c1d4d15737fdf5dd4c721d"
+ "digest": "b3881060569e56e1dd75ca7960feab0e58ae51f440458781948d65d461116b4e"
},
{
"name": "+1_tone3",
"unicode": "1F44D-1F3FD",
- "digest": "0bb7bbfb654c6139260e1786e7ffa5a33f31e19410c1d4d15737fdf5dd4c721d"
+ "digest": "b3881060569e56e1dd75ca7960feab0e58ae51f440458781948d65d461116b4e"
},
{
"name": "thumbsup_tone4",
"unicode": "1F44D-1F3FE",
- "digest": "df0927c5342f0075fbf4ea83b724e6f70c0466c54769c9ce4a5c2deb602b28aa"
+ "digest": "86fbe2c95414bce5e38fb5c33da31305d7942fca2c9c79168dcffdbd895e9ad6"
},
{
"name": "+1_tone4",
"unicode": "1F44D-1F3FE",
- "digest": "df0927c5342f0075fbf4ea83b724e6f70c0466c54769c9ce4a5c2deb602b28aa"
+ "digest": "86fbe2c95414bce5e38fb5c33da31305d7942fca2c9c79168dcffdbd895e9ad6"
},
{
"name": "thumbsup_tone5",
"unicode": "1F44D-1F3FF",
- "digest": "0683ae08c50aaf186c6406680a60617679c7b4bccd0817f24b15911dbb06866f"
+ "digest": "49fa63ff725c746a18649df16c8fab69bad88bbb564884df79d1d15f553b7343"
},
{
"name": "+1_tone5",
"unicode": "1F44D-1F3FF",
- "digest": "0683ae08c50aaf186c6406680a60617679c7b4bccd0817f24b15911dbb06866f"
+ "digest": "49fa63ff725c746a18649df16c8fab69bad88bbb564884df79d1d15f553b7343"
},
{
"name": "thunder_cloud_rain",
"unicode": "26C8",
- "digest": "dd836f06b41a10d6ed9bcbdae291d2886847ff66dc3ede2427382e469f60674c"
+ "digest": "dacc20b4f6b68e5834aa1b8391afa5e83b5e6eb28e2d2174d3a68186a770506d"
},
{
"name": "thunder_cloud_and_rain",
"unicode": "26C8",
- "digest": "dd836f06b41a10d6ed9bcbdae291d2886847ff66dc3ede2427382e469f60674c"
+ "digest": "dacc20b4f6b68e5834aa1b8391afa5e83b5e6eb28e2d2174d3a68186a770506d"
},
{
"name": "ticket",
"unicode": "1F3AB",
- "digest": "a7654a5529535120da3c377e72cd1f7997bdc2dabf1d44b584f7df7852b158f9"
+ "digest": "b4326fe7761940216e6c76ee2928110a6b37bf913da9d694e96557e7c7c10420"
},
{
"name": "tickets",
"unicode": "1F39F",
- "digest": "ccafcc9583a84e847ff1eaa3d53187c5ab150a7d27c6a19363e59b9bc046b567"
+ "digest": "fb73358c3697c04fcfde6a1e705b1c3b47635b93b9cadfe31d5657566c7d190a"
},
{
"name": "admission_tickets",
"unicode": "1F39F",
- "digest": "ccafcc9583a84e847ff1eaa3d53187c5ab150a7d27c6a19363e59b9bc046b567"
+ "digest": "fb73358c3697c04fcfde6a1e705b1c3b47635b93b9cadfe31d5657566c7d190a"
},
{
"name": "tiger",
"unicode": "1F42F",
- "digest": "9ebe3117f5f1b589ff8164f8d87dcc275923e0db87121d2cee0fdb9b56dfc4ac"
+ "digest": "e139531e6c930bc46242dc0ed274661229de026b5419d8ea8f99fdb0f8a719ab"
},
{
"name": "tiger2",
"unicode": "1F405",
- "digest": "212c95dc60d52420a6320917fe3fdd0683b4edc1a2a2c4a1c60920d1f90f4bc3"
+ "digest": "f930cc8714198310d9b0edca6baff243ac5a3320f75fadb56fa5acc6fe34ff24"
},
{
"name": "timer",
"unicode": "23F2",
- "digest": "c48199312ed42ff53a33bb2791db19e2e2521223cd49d8f758ea95b9b379c5ff"
+ "digest": "69b33f219523d89d81cbbc070ad7e528711e4b34e124a50acb12a0280a34d0b0"
},
{
"name": "timer_clock",
"unicode": "23F2",
- "digest": "c48199312ed42ff53a33bb2791db19e2e2521223cd49d8f758ea95b9b379c5ff"
+ "digest": "69b33f219523d89d81cbbc070ad7e528711e4b34e124a50acb12a0280a34d0b0"
},
{
"name": "tired_face",
"unicode": "1F62B",
- "digest": "ad687a956388ec53ca1e301a0abe2f1e2cfb9f73cd543dd61a21c7335a42e332"
+ "digest": "775739bc9324517e614878ca0960d793df97775feeb62b14dbfb311a42a21802"
},
{
"name": "tm",
"unicode": "2122",
- "digest": "1156c8b0af40b336bbb6534b3302ac63eab009c4cd0476adcf1fc4669f04b647"
+ "digest": "7d9fafdb72d91860478fc185719f289f359eab2c368a132cb936a269e2ab6a24"
},
{
"name": "toilet",
"unicode": "1F6BD",
- "digest": "a4a24529c21e00e0861f4160c771f0e90aae8f6aee7550ad30d3dbb3fabbd4be"
+ "digest": "0d1b0dd0078f51104e8632a0726e1b3f075561a1ffa8a2546602de15798415d0"
},
{
"name": "tokyo_tower",
"unicode": "1F5FC",
- "digest": "6324f154f5f5c722044129e5bca03484aca1439911585e42c1c181ffa30b480c"
+ "digest": "73eaf6fd59d16396673afef620c6d928857d5cf616e95a40eaf2861686e0956a"
},
{
"name": "tomato",
"unicode": "1F345",
- "digest": "41bb6de095b27815eacb74a70aea8f7d4fe1ff947182b112001dd47ae7e45fbb"
+ "digest": "d092d8ad381d542e59b6a82b4f1ef0d10fc1ed48460952375c6c5c6258cea111"
},
{
"name": "tone1",
@@ -10247,72 +10247,72 @@
{
"name": "tongue",
"unicode": "1F445",
- "digest": "bf9dd7c65a8dc5d77eb013658a0a12a13f7b224a784e65e203d9584bb6b41427"
+ "digest": "286e9d2583c371431d6fc979dd4ab48981676da26baada51a846657a3654c19b"
},
{
"name": "tools",
"unicode": "1F6E0",
- "digest": "9b0a36dfdb475621d326359662b22cbdb80563c4f476aa5e7d7c00cdba605bd9"
+ "digest": "bf08d60dedc06de73d04dab05703bb8ad81989c72b5035d1a07821e51096f158"
},
{
"name": "hammer_and_wrench",
"unicode": "1F6E0",
- "digest": "9b0a36dfdb475621d326359662b22cbdb80563c4f476aa5e7d7c00cdba605bd9"
+ "digest": "bf08d60dedc06de73d04dab05703bb8ad81989c72b5035d1a07821e51096f158"
},
{
"name": "top",
"unicode": "1F51D",
- "digest": "d645030099aeb433307569e8e1c4342c1c411a8fefe50fdca7a3207a1a0db671"
+ "digest": "c9a9f25b17db014e76b6be54aa07ef89bb18f8adb41b3199d180a559ff1d9ea5"
},
{
"name": "tophat",
"unicode": "1F3A9",
- "digest": "1082fb2ee2e98fe65d21081b74ca59b07adef85043e2d36f25cac69db2d31fd3"
+ "digest": "43a45dfb5d6b57a63a0491f4e3ec780774c0301b53ed39a303a0bd803d16ed71"
},
{
"name": "track_next",
"unicode": "23ED",
- "digest": "d5415ed140933f345fea8023a3d8fca30dcfcf7d19d9dc9771fa2cae9df62a3b"
+ "digest": "88592ef6c720a32aeb752322fb4c794bf5110a72408e21e898630452115c731c"
},
{
"name": "next_track",
"unicode": "23ED",
- "digest": "d5415ed140933f345fea8023a3d8fca30dcfcf7d19d9dc9771fa2cae9df62a3b"
+ "digest": "88592ef6c720a32aeb752322fb4c794bf5110a72408e21e898630452115c731c"
},
{
"name": "track_previous",
"unicode": "23EE",
- "digest": "97ff4a59a236e5cf506fa3577b20715b3b0197e0f343a50615b36185d5b835f1"
+ "digest": "98c1b3d643768d94857fb762f6d26cfb87282b449a67792242e8b7068643ac87"
},
{
"name": "previous_track",
"unicode": "23EE",
- "digest": "97ff4a59a236e5cf506fa3577b20715b3b0197e0f343a50615b36185d5b835f1"
+ "digest": "98c1b3d643768d94857fb762f6d26cfb87282b449a67792242e8b7068643ac87"
},
{
"name": "trackball",
"unicode": "1F5B2",
- "digest": "8332503454ce42059d720c285fe2b15eb0562a0a4b234dccb0f3159bb30a91aa"
+ "digest": "32a819a3129429f797ad434d0c40e263dc236808e34878c599ed2304b43702f5"
},
{
"name": "tractor",
"unicode": "1F69C",
- "digest": "a41d304c41a85d966f6a7c301735fdbe2ae41f4471dd7dcd72023046ca2546d0"
+ "digest": "5e4686290f1a4c9953ae208340b7d276f25b3b2197a43e52469aeb6450e93997"
},
{
"name": "traffic_light",
"unicode": "1F6A5",
- "digest": "005f68d028fec8d9ae389cc2b23e1343a82c028eb32820d5e56f5c84eba315d1"
+ "digest": "d96aacade33d1ad3e0414f8a920513010f36eb7e5889774251c1d91148917ead"
},
{
"name": "train",
"unicode": "1F68B",
- "digest": "bf32893b7b9ecd248e8afe840624061746ac6ceb741e3e861ebfa46014f4bed4"
+ "digest": "7423d17e131df7aadaa350b5d39dcbce3b28de331ff8b6703a3b2d0093963f4b"
},
{
"name": "train2",
"unicode": "1F686",
- "digest": "08a9732453a0b4f68dd2d3d3879f04ee538f65897913b5a5157c0585132a374a"
+ "digest": "06e65d549e771632f3c64287a38ba67236f9800ccb6a23c3b592bc010e24e122"
},
{
"name": "train_diesel",
@@ -10327,7 +10327,7 @@
{
"name": "tram",
"unicode": "1F68A",
- "digest": "5a86d31f7ab677d967fecd75babc900b5169766d0228961912314c4c4d1d64ee"
+ "digest": "21a7699f1a94f06dcb4d1e896448b98a4205f8efe902a8ac169a5005d11ab100"
},
{
"name": "triangle_round",
@@ -10342,62 +10342,62 @@
{
"name": "triangular_flag_on_post",
"unicode": "1F6A9",
- "digest": "d824c973d84cd62c845d64e546de87b094fda8f9972b6a33acd75e1a5ac19f75"
+ "digest": "1f5ce3828a42f5b1717bac1521d0502cf7081ad9f15e8ed292c1a65f0d1386da"
},
{
"name": "triangular_ruler",
"unicode": "1F4D0",
- "digest": "5576802d8bcb8836f473d9c7641ff666250c23c8476c676b253e577695025959"
+ "digest": "a0367dcf663ec934f1fc7c88bfaccc02b229a896f60930a66bb02241c933e501"
},
{
"name": "trident",
"unicode": "1F531",
- "digest": "70c1e8254da5b0e4552673b487503a20feeb249484d4596836b75de70220be82"
+ "digest": "ee45920845d3b35c2e45b934cf30ce97bfe2f24c5d72ef1ac6e0842e52b50fc1"
},
{
"name": "triumph",
"unicode": "1F624",
- "digest": "b09262121b0d3d9d017ded22d0fbb1acaa6ee8c9d38e9ac34292b390d97408fe"
+ "digest": "4aa44b8e1682c1269624a359f4b0bf613553683b883d947561ab169d7f85da0f"
},
{
"name": "trolleybus",
"unicode": "1F68E",
- "digest": "5af943836cc30c3b79160c70b6488c984fa63c104dce08c436597a93d30ff6f4"
+ "digest": "f610b4fd1123f06778a8e3bb8f738d5b0079aeb0b0926b6a63268c0dd0ee03ed"
},
{
"name": "trophy",
"unicode": "1F3C6",
- "digest": "c249938815042716db2b39cdece6715fabf9e56ed583270c451925e6c91f9191"
+ "digest": "50cfbedac18bf0fa5dec727643e15ec47f64068944b536e97518ee3be4f08006"
},
{
"name": "tropical_drink",
"unicode": "1F379",
- "digest": "352d903e813a27d2a74803322539b50a50aec0ca2ed7ab4a92ec480b1c226cb6"
+ "digest": "54144fce60d650f426b1edf09e47c70b2762222398c1fe40231881f074603a69"
},
{
"name": "tropical_fish",
"unicode": "1F420",
- "digest": "13a104ca9c326238ab8d85b60759629b4efaa836946fbe58d78d779443475f7b"
+ "digest": "fd92100aaa9328da35e6090388824921b9726b474d1432a926d2cf9c45ad6528"
},
{
"name": "truck",
"unicode": "1F69A",
- "digest": "13d381d6b43b42350a1e24c02296904b8fdc38c1bf0939fc7037850127e91f21"
+ "digest": "0d1571e58e900abc453df0ff683fe7acb5906ecbdd52ab35b7101074359faf18"
},
{
"name": "trumpet",
"unicode": "1F3BA",
- "digest": "df7fb48920ac0919ee2d7b30102016479f747a5d4dd25b3e18d9f17121d232d1"
+ "digest": "cea3614c309f5573f328f4603120dbe930016a35f0dfa400b0d968fe9fff2d55"
},
{
"name": "tulip",
"unicode": "1F337",
- "digest": "519a84336464b5dc8db57eecef3e5b8ed82ccfdaa0ed0fa9ef7bcf0e8acea1f8"
+ "digest": "e744e8dbbdc6b126bd5b15aad56b524191de5a604189f4ab6d96730dfef4d086"
},
{
"name": "turkey",
"unicode": "1F983",
- "digest": "e87bff52ad3e301dc62f6832b8a6fcaf99db260a96263e4203a55ce3abda8cf8"
+ "digest": "bf5daef15716b66636a5fdb6d059420521443c0603e2d56bd7c99c791a7285f4"
},
{
"name": "turned_ok_hand",
@@ -10412,442 +10412,442 @@
{
"name": "turtle",
"unicode": "1F422",
- "digest": "388b3e75b931638a09f65b842d26e2cc87b200ba782dec871f84cddd71aaeaf3"
+ "digest": "588c35fb42c9502a908e9805517d4cc8c4ba4e74c9beed4035779fea1efe14f8"
},
{
"name": "tv",
"unicode": "1F4FA",
- "digest": "dba03be6482d6291599c7393b0f749c0de5c873d45c96a20ccc53b3e104a6a24"
+ "digest": "1279f3f3955a58dbbf74e248fc914b0bdba9c4c6b6a5176e9d12bf2750ecfeb4"
},
{
"name": "twisted_rightwards_arrows",
"unicode": "1F500",
- "digest": "5fcad0247576e10e683f353008749975e9371a4f66c0901a73c3a0c7803c63c7"
+ "digest": "fed07eebc2cf0d977ca0826bbd80defafbbcf118508444148f47b58949ebe27c"
},
{
"name": "two",
"unicode": "0032-20E3",
- "digest": "20ad722532a5073fff8aef0a5e890421da0ae97f0723a8a2cc503c13d24ba597"
+ "digest": "b346f51f6523b02ebcbd753256804e2f9cc1574c96aa634362bf9401dac2c661"
},
{
"name": "two_hearts",
"unicode": "1F495",
- "digest": "160cb11e3ed2ae1b20957d445c6c4b4bd604d067294818dfeeefba4562425eb9"
+ "digest": "6ded120a59aed790b441ec8fbbdea6f5cbfb4fa48e9e4b224cc29c9fde2d2e4c"
},
{
"name": "two_men_holding_hands",
"unicode": "1F46C",
- "digest": "923734704e544f7484fdb424bfe26f51ee07754db712cd151f8fbe955023a1ab"
+ "digest": "bfcf9e20a67d00262cdf6e85f1acd545dda91f2e370d68bfd41ce02f232a2987"
},
{
"name": "two_women_holding_hands",
"unicode": "1F46D",
- "digest": "58a40e7819cab3589ac81bb4fdc485b7196ee355544b54c6b00169028c260130"
+ "digest": "9d9d2b37a7f8e16fde1468dd8b5645003ea81ae4bf8bcf68471e2381845dd0dd"
},
{
"name": "u5272",
"unicode": "1F239",
- "digest": "b7e8ad52629a1f1fca77a5c9a51da87ce2b9a81f6af9bcbe9bec9552d398e9bf"
+ "digest": "01e6cb8f74ea3c19fdade59c2d13d158b90dc6b4b293421b2014b7478bf20870"
},
{
"name": "u5408",
"unicode": "1F234",
- "digest": "f359799d206cff6aae3af26eb8ad153abd38e817d4c70b2e5e5e8cf2f46e645e"
+ "digest": "084cdbd5436670ea4dc22010e269c1ab7b0432897b8675301e69120374bcdd14"
},
{
"name": "u55b6",
"unicode": "1F23A",
- "digest": "c40293bea0f148e76ca5152e830b1b474380fe259180fbf74fece1ccc9afd8a3"
+ "digest": "c1017023d20d4aae78d59342dd3bfc5282716ea0601d9a8c2476335cbf7a2e12"
},
{
"name": "u6307",
"unicode": "1F22F",
- "digest": "45449f7ae29da9e507c19d0f2b22f17f7cbd763f2ec87eb893be5bae49c7f78e"
+ "digest": "f459b092b974f459db1fb9cc13617a448b2e4f2b4dc46cc316d8c46af6e7d8bd"
},
{
"name": "u6708",
"unicode": "1F237",
- "digest": "b897ead8c952013975ce6f381cdb8c584ebe4015311ef87f2a332c8a9e155d75"
+ "digest": "928815abf5b30f92efe5168de0c7e6cf8c17899a03e358ab42f42667e0a4a04c"
},
{
"name": "u6709",
"unicode": "1F236",
- "digest": "8b2f792abc1313a1a58f2fb8b37ad68a964004c962535f7739131257b1331a05"
+ "digest": "f63a48ee06c892d24acec8b5634c021658d2ebde67a42d8faa86f27804a9f26d"
},
{
"name": "u6e80",
"unicode": "1F235",
- "digest": "fd982a56d4c492e63526b427bb948d7f155b0d5c414a68c7177698a71e72269b"
+ "digest": "489181d90a5e43068459530673a153e4af04fdad8514ec341ff7afbcfd366c3b"
},
{
"name": "u7121",
"unicode": "1F21A",
- "digest": "334f87a5254b58503d9f7a8ecc3d971a99839ec9c22c443469d72caca1750a48"
+ "digest": "9c50fd2ba14221affd2dcd3746322c2137dd75458493f4d385b544eb5bd8d6cd"
},
{
"name": "u7533",
"unicode": "1F238",
- "digest": "3c8e743ae9960e43b9fa0cc698018fcb2a52ae34d143f0561298191f9def019c"
+ "digest": "2b05819b380a2ea47cc5fde8fcce3d53922fd223d6f5bd83d696d44175b69f18"
},
{
"name": "u7981",
"unicode": "1F232",
- "digest": "a08bf39be3a54c076de79478c09b79c5c4d221853722870dd6e81abb78a4b64a"
+ "digest": "adbe12601b22972003ddebcb0bd1532b979aa9c78bfdc147511854b5014eabc0"
},
{
"name": "u7a7a",
"unicode": "1F233",
- "digest": "5dfb74a534a6490df989f84eac271c79d52f29313b6d43662dd0ff029794367c"
+ "digest": "b9ee0ec7bb0b86c3eb73d4dbbb91848c427bf356ae30a263b9b44bd9bd784482"
},
{
"name": "umbrella",
"unicode": "2614",
- "digest": "ff1191f6c11b82f5337f78aadb58af50c69abaf676a384b0473bf49004e4018f"
+ "digest": "0328a2f48b7df47905e2655460e524c0794ef12d3d7c32a049a10892d5662f77"
},
{
"name": "umbrella2",
"unicode": "2602",
- "digest": "aa7db9d6ed42dff847a8e5ee48a8eeff7a6e7f30de155a28951407f5aaa3dae2"
+ "digest": "2f6a58110dc590480a822a3ffa2b5bc86f295e0c994a4a632837d25d4cf9fc58"
},
{
"name": "unamused",
"unicode": "1F612",
- "digest": "efbbcaee6f3178afe509d74d13243ec6befe3112620a01e5079171eac4b32417"
+ "digest": "0d597088e3e7880918d0166e5c69243b18fe64afa31685c39bfdbc71494aa132"
},
{
"name": "underage",
"unicode": "1F51E",
- "digest": "ae9a300fa400a57b7216a0a040fb8a5f02236fbceeeceed58bfd953c87ad51fe"
+ "digest": "b6b194614ca714ac2b1c2c17b75fe5922c7fdadb3d1157ba89ab2a5d03494a67"
},
{
"name": "unicorn",
"unicode": "1F984",
- "digest": "1b1e9c209dabe619db76fd346c3fb51b28ace0e4102697fe0973fe2d46aa9f08"
+ "digest": "f71bb485a7c208e999dd45f2b36d7b7d517898c0627947926b05aa28603804ca"
},
{
"name": "unicorn_face",
"unicode": "1F984",
- "digest": "1b1e9c209dabe619db76fd346c3fb51b28ace0e4102697fe0973fe2d46aa9f08"
+ "digest": "f71bb485a7c208e999dd45f2b36d7b7d517898c0627947926b05aa28603804ca"
},
{
"name": "unlock",
"unicode": "1F513",
- "digest": "63dbef0855399254ae01cf4ef0676adebc1432ae1ee260b569c23ae8152deaf8"
+ "digest": "9554ef3a6a315938b873e77970d9b0212e61f13c6cc36e4f17f87acc930a9a53"
},
{
"name": "up",
"unicode": "1F199",
- "digest": "902a3ecbcd73099a28476b49bc9e7b06da6cc002ee584e0501e5b625fb515088"
+ "digest": "ff2554ccf08c7208b38794c5fa3d9a93a46ff191a49401195d8f740846121906"
},
{
"name": "upside_down",
"unicode": "1F643",
- "digest": "763fe2baf07a9b04f96958adf38a43c7dd2bc70d57398f49604307bd835cbb53"
+ "digest": "5129121f0a28f5b334268c28565de26a5907559568deca11de6ec620b097dfe1"
},
{
"name": "upside_down_face",
"unicode": "1F643",
- "digest": "763fe2baf07a9b04f96958adf38a43c7dd2bc70d57398f49604307bd835cbb53"
+ "digest": "5129121f0a28f5b334268c28565de26a5907559568deca11de6ec620b097dfe1"
},
{
"name": "urn",
"unicode": "26B1",
- "digest": "dbfd5b90709d1b812d2fff71a5cfa10f84a4579866c2d7cd0e80759a22b2ba0e"
+ "digest": "9bebf589eed8dd361f6a03cd1b325078f2cd0e82270ef63a7dd1b6aee08cd1e6"
},
{
"name": "funeral_urn",
"unicode": "26B1",
- "digest": "dbfd5b90709d1b812d2fff71a5cfa10f84a4579866c2d7cd0e80759a22b2ba0e"
+ "digest": "9bebf589eed8dd361f6a03cd1b325078f2cd0e82270ef63a7dd1b6aee08cd1e6"
},
{
"name": "v",
"unicode": "270C",
- "digest": "df85ad1a3ff365c3232a010701c9b25cd824d19fa2511422dee60ac231f457e3"
+ "digest": "9825bf440df289a8edf8ede494e8c778dc63c95f967f4d7bbea3245cf4f558ec"
},
{
"name": "v_tone1",
"unicode": "270C-1F3FB",
- "digest": "ce45db8de862b6f37d9208920d7c7c19335fac2cbff59b52be1ccbc01e3249da"
+ "digest": "76e358250d9ca519b60b8d7b6a32900700d784433dcc609e9442254a410f6e37"
},
{
"name": "v_tone2",
"unicode": "270C-1F3FC",
- "digest": "9036c8d793b02b4d2e6a4752b8ec319ec50efd6fcd6feef7b0671a63e5659acc"
+ "digest": "4081b674be8416136022523fa9f29ec70a0f7e3aa05ca13152606609f3fd003c"
},
{
"name": "v_tone3",
"unicode": "270C-1F3FD",
- "digest": "a94b95f7656d62b442c99f2643b96b0c6114683401a94cdda68405c37efecc4c"
+ "digest": "b6afb3a4c78384280610b953592d378241c75597a82aa6d16c86a993f8d8f3b0"
},
{
"name": "v_tone4",
"unicode": "270C-1F3FE",
- "digest": "5c75f74993856f2faeeaee68df7689056e60d30e8c573039db8303167f7d0a80"
+ "digest": "7ddc3cdd0138da2c8d7f6d8257ffdb8801496043e8a2395f93b0663447ac7fce"
},
{
"name": "v_tone5",
"unicode": "270C-1F3FF",
- "digest": "bb899672adb3c11f65983fbf9581de7f0a1bbac86fde146e799cea1126fe241e"
+ "digest": "a85dc5c589f0d1cf32f8bfa5c82e5c11c40b35439636914686a2f06f7359f539"
},
{
"name": "vertical_traffic_light",
"unicode": "1F6A6",
- "digest": "36296e03620f16d35e5cec195cd97f5b358dfdedcd43bc1b3f7988ff7e85ab47"
+ "digest": "8cfd49a8f96b15a8313ef855f2e234ea3fa58332e68896dea34760740de9f020"
},
{
"name": "vhs",
"unicode": "1F4FC",
- "digest": "f4be55f4c23a85e0caacbf569742c117c8fd52c189465a6560cbd2f8873ad74f"
+ "digest": "3fb1acaf25805cf86f8d40ee2c17cf25da587b7ca93b931167ab43fce041eee8"
},
{
"name": "vibration_mode",
"unicode": "1F4F3",
- "digest": "b9b8dfa3160c22f78b7d627cb52636d81ca6230a196cee5e94028e32e06b9a98"
+ "digest": "c9a8899222f46fe51dd8cee3e59f77c48268f0b7cfae2bcb34a791213acb1755"
},
{
"name": "video_camera",
"unicode": "1F4F9",
- "digest": "3bfaa24e5fb00145e3e4dd07ecf569dabbb3f211551e46085ef23cf23002cfc3"
+ "digest": "62e56f26c286a7964ef1021f0f23fcb4b38cdcfb5b5af569b472340c412c619a"
},
{
"name": "video_game",
"unicode": "1F3AE",
- "digest": "4dcbd76030e37d0f7429852991a5f3f126cbdedfc124ecad0ba29d227375f6e2"
+ "digest": "2787e302aa9e6fd7e9dc382c9bc7f5fbf244ef4940e08a4f9e80d33324f3032e"
},
{
"name": "violin",
"unicode": "1F3BB",
- "digest": "8ab7adc6e1e934f9e05009cd0a6d4da3136092c8f11c0606b91914be182206f5"
+ "digest": "1e69d531ce2b5d5bf1dd9470187dbbe76f479d14428834b6a9e2bf5296dc0ec9"
},
{
"name": "virgo",
"unicode": "264D",
- "digest": "aaa19752756d0cac949445de1d2b8bf1f75a071368ae0acf5002f4acdc34826f"
+ "digest": "0f75e9c228bc467fd0cec0f93f0e087c943bc5fb1d945fb0d4de53d07718388e"
},
{
"name": "volcano",
"unicode": "1F30B",
- "digest": "86c17d61d66bfa868c02f1d31daca22f077c096368ef53cd9bfb9914a2f0b273"
+ "digest": "41c92ef88ca533df342a0ebe59d2b676873bfa944c3988495b8a96060a9b8e16"
},
{
"name": "volleyball",
"unicode": "1F3D0",
- "digest": "b505684b13f814fbc08dc8ff652849328f46068276e0a24ae1961e2aff15868f"
+ "digest": "774a83357f7aee890b4d4383236f0a90946dbd7c86aaabadc5753dcc9b4c9d69"
},
{
"name": "vs",
"unicode": "1F19A",
- "digest": "e31bd8b48b88c21d717964d1360a7751684dd1e0b63fdd655f1a9ec10a952dfb"
+ "digest": "ac943e4c737459c2e1adbac8b71d3fdaebb704dbaf5713012e7a77beb09db1ef"
},
{
"name": "vulcan",
"unicode": "1F596",
- "digest": "ca800fce797e652c5f47bf44992e8fbe19554688a36423fdf7c29ca6defae1e0"
+ "digest": "b4d409a0b019e7b06333cefd15ea46cb54aef5132d86e8ba361c1c3b911fe265"
},
{
"name": "raised_hand_with_part_between_middle_and_ring_fingers",
"unicode": "1F596",
- "digest": "ca800fce797e652c5f47bf44992e8fbe19554688a36423fdf7c29ca6defae1e0"
+ "digest": "b4d409a0b019e7b06333cefd15ea46cb54aef5132d86e8ba361c1c3b911fe265"
},
{
"name": "vulcan_tone1",
"unicode": "1F596-1F3FB",
- "digest": "84bafdaca43426b053f5caa4e868ca109d99113a28ea9799db09d3c5d5f645c8"
+ "digest": "cc6072c85031b5081995f98a57f09ab177168318f69a51f3acc63251760499a4"
},
{
"name": "raised_hand_with_part_between_middle_and_ring_fingers_tone1",
"unicode": "1F596-1F3FB",
- "digest": "84bafdaca43426b053f5caa4e868ca109d99113a28ea9799db09d3c5d5f645c8"
+ "digest": "cc6072c85031b5081995f98a57f09ab177168318f69a51f3acc63251760499a4"
},
{
"name": "vulcan_tone2",
"unicode": "1F596-1F3FC",
- "digest": "e7cedf63ead957ee5c287e4cb0828ba70673e17b604f92b529875c32d094e7e3"
+ "digest": "858bd5a1ac91dc4d7735f57ba4dd69d39138aa6dac1c80cfc05de30a59a5bc33"
},
{
"name": "raised_hand_with_part_between_middle_and_ring_fingers_tone2",
"unicode": "1F596-1F3FC",
- "digest": "e7cedf63ead957ee5c287e4cb0828ba70673e17b604f92b529875c32d094e7e3"
+ "digest": "858bd5a1ac91dc4d7735f57ba4dd69d39138aa6dac1c80cfc05de30a59a5bc33"
},
{
"name": "vulcan_tone3",
"unicode": "1F596-1F3FD",
- "digest": "e124fef20f289921553274cf834f6dcc1a012889d30d9874dc5ad01afb8235b8"
+ "digest": "2f74b6f3eab2a75063591b66f1c7350af0d23153e1427af91de20c48a5f4a54a"
},
{
"name": "raised_hand_with_part_between_middle_and_ring_fingers_tone3",
"unicode": "1F596-1F3FD",
- "digest": "e124fef20f289921553274cf834f6dcc1a012889d30d9874dc5ad01afb8235b8"
+ "digest": "2f74b6f3eab2a75063591b66f1c7350af0d23153e1427af91de20c48a5f4a54a"
},
{
"name": "vulcan_tone4",
"unicode": "1F596-1F3FE",
- "digest": "ea2115f549e4680467521bbf362b229f4a8f0fdadbfaf231378d801f9b369f08"
+ "digest": "87cf8b87d3610f742857a9704b658462df32b4924d8f1ddba26f761e738c4e11"
},
{
"name": "raised_hand_with_part_between_middle_and_ring_fingers_tone4",
"unicode": "1F596-1F3FE",
- "digest": "ea2115f549e4680467521bbf362b229f4a8f0fdadbfaf231378d801f9b369f08"
+ "digest": "87cf8b87d3610f742857a9704b658462df32b4924d8f1ddba26f761e738c4e11"
},
{
"name": "vulcan_tone5",
"unicode": "1F596-1F3FF",
- "digest": "1b322e1252491f35ae02f0b279b6529dad867f2a6b3c2c3e77f981bed07e447d"
+ "digest": "11e9ff62f2385edeb477dbf66c63734536531def5771daf80b66a3425ac71493"
},
{
"name": "raised_hand_with_part_between_middle_and_ring_fingers_tone5",
"unicode": "1F596-1F3FF",
- "digest": "1b322e1252491f35ae02f0b279b6529dad867f2a6b3c2c3e77f981bed07e447d"
+ "digest": "11e9ff62f2385edeb477dbf66c63734536531def5771daf80b66a3425ac71493"
},
{
"name": "walking",
"unicode": "1F6B6",
- "digest": "8ec0b2207d4368422261bc58944c17dff2554b2356becfb18f21dd87425cd67b"
+ "digest": "ae77471fe1e8a734d11711cdb589f64347c35d6ee2fc10f6db16ac550c0557fa"
},
{
"name": "walking_tone1",
"unicode": "1F6B6-1F3FB",
- "digest": "9ee2224226326833fb0c9598c737fbd2f6bca1c81f082537e9f22ea1de4ff48e"
+ "digest": "3de871c234e1340ccf95338df7babd94d175cfcb17a57b5a74d950e0a31f03b1"
},
{
"name": "walking_tone2",
"unicode": "1F6B6-1F3FC",
- "digest": "4855d521e937d10d58eeb2bbada493699e31e1098128f81a9e3303bcf3edeb49"
+ "digest": "620eb7bfb753a331a5822b02bdaf08d8dde7b573efd210287a3d3dfdd84a40b9"
},
{
"name": "walking_tone3",
"unicode": "1F6B6-1F3FD",
- "digest": "82669cf7167054a3615add01059f87dbb809edac3889ee171d5994de90448000"
+ "digest": "ff39545acc2256006128f8c186433c28052b8c9aaec46fe06f25cff02c71f6b8"
},
{
"name": "walking_tone4",
"unicode": "1F6B6-1F3FE",
- "digest": "c11f03aa96248272f831f68b93c5b21b2ecbffeb1b4c1c13373bf539ee7db8f8"
+ "digest": "a9499d142392977a9b9e54fb957952359e9bdffce7ec2f1e8320523d185fb066"
},
{
"name": "walking_tone5",
"unicode": "1F6B6-1F3FF",
- "digest": "18238ee121a64211f6bcdbd475cee4ad6debe2bf421daba53d125aa005c26d10"
+ "digest": "b47a4c48ce40298f842f454fc1abccae70f69725d73ee2c80e4018f4c4065d7d"
},
{
"name": "waning_crescent_moon",
"unicode": "1F318",
- "digest": "96ef03ff85247877255a5ca3e8a8bb63f7d41f66531e8db61cbcd863e3ad7355"
+ "digest": "2ec7896eefcf821e0ea013556a17af59e997503662c07f080d0a84ab13ef4cf1"
},
{
"name": "waning_gibbous_moon",
"unicode": "1F316",
- "digest": "994223113ad151e6b42ee317a10dad18f86759a308e61ab88eeb10ab780aae67"
+ "digest": "ce2f5aca8fccdacaaf174d10da4e493e853e4608cc4d159aa3081d108a8b58d5"
},
{
"name": "warning",
"unicode": "26A0",
- "digest": "a702e51efd1a3ab425eada008ccf694f38a71db14bb710edacc2e206d61f5ca3"
+ "digest": "745f1d203958f42bf37ecb5909cd0819934e300308ba0ff20964c8c203092f90"
},
{
"name": "wastebasket",
"unicode": "1F5D1",
- "digest": "afecb31aaf5078298ab9f7c5da29a49ce0cdefe477ee50889be9c0e43ccf1799"
+ "digest": "221a1b6d9975051038d9d97e18a16556cdf4254a6bca4c29bf1c51f306c79f2a"
},
{
"name": "watch",
"unicode": "231A",
- "digest": "410334c87b8552f601f4ea1b7e36582a8b22f11b804d5ab1008d4af2b5a0cbe6"
+ "digest": "acc0c96751404a789b3085f10425cf34f942185215df459515d2439cde3efc6b"
},
{
"name": "water_buffalo",
"unicode": "1F403",
- "digest": "d1becfaea464372c46e5442c6030ea355806ce5864c2435c123a9bb3a2c3c5eb"
+ "digest": "ba6a840d4f57f8f9f3e9f29b8a030faf02a3a3d912e3e31b067616b2ac48a3d1"
},
{
"name": "watermelon",
"unicode": "1F349",
- "digest": "88dd78812520c44080c79fe8cb1825bc713e5155da2ce8c73286333749e7035e"
+ "digest": "42a3821d2e4dd595c93f5db7a5c70b7af486b8f0ddd3b9d26bc4e743a88e699a"
},
{
"name": "wave",
"unicode": "1F44B",
- "digest": "5103c49914ff1a2d76a1ab6db2530ddd9f48b98b708ab15292ceadf28873c939"
+ "digest": "cddbd764d471604446cbaca91f77f6c4119d1cfc2c856732ca0eaac4593cb736"
},
{
"name": "wave_tone1",
"unicode": "1F44B-1F3FB",
- "digest": "ef2d79f377d09dedd1e900b2f4e4a2412bf562cd88484f71c52d465053f8aae9"
+ "digest": "cf40797437ddf68ec0275f337e6aac4bed81e28da7636d56c9f817ddf8e2b30a"
},
{
"name": "wave_tone2",
"unicode": "1F44B-1F3FC",
- "digest": "d323e6e2e9ce035bc11b98226d46ab393dfdf3909d99e7a828b51950e6574656"
+ "digest": "12c8a3e82c03ee35a734c642be482ba2d9d5948dacf91ec1fda243316dd4a0d0"
},
{
"name": "wave_tone3",
"unicode": "1F44B-1F3FD",
- "digest": "8a8a386d53252455c20d6b235c462fd9cb3b20c9c19c67e67b3dece4621b5cf6"
+ "digest": "ebcaef43e21b475f76de811d4f4d1a67d9393973b57b03876e02164345a2ba4a"
},
{
"name": "wave_tone4",
"unicode": "1F44B-1F3FE",
- "digest": "a8281c2ab9cf6e2b3d3cad24707fe412ec2398195530b716a2617477416c0432"
+ "digest": "7df7b70cf76766836ba146c3d91b6104930c384450cf2688426e60c1c06a1fc8"
},
{
"name": "wave_tone5",
"unicode": "1F44B-1F3FF",
- "digest": "5ccbee95bfc180580c8a02b88146110c4d132b8ea618dd6a58f03c1db921d58d"
+ "digest": "8dfdba6aeff5d7dfd807467d431a137547726b34d021f1a5a0b74e155d270ea7"
},
{
"name": "wavy_dash",
"unicode": "3030",
- "digest": "b5b67fc12938801a98ff22b6f7b566c603f58c183737fa740a500724879f0e99"
+ "digest": "7b1968474f01d12fd09a1f2572282927138d9e9d6a3642de4bf68af80a8c3738"
},
{
"name": "waxing_crescent_moon",
"unicode": "1F312",
- "digest": "20446122d170b18f88ea71524f6747d42b97f9d765c52e676e5163fee58ec379"
+ "digest": "852d7e55a19074d061fa3aa80d6b1e7e87a9280bdf44d94bbdbbe6d59178b1be"
},
{
"name": "waxing_gibbous_moon",
"unicode": "1F314",
- "digest": "4324e43d4d45e6333f7379c9feb8efd3093d76f3920d7dc5ad3c615e76104998"
+ "digest": "a3a1c7cc72521a3f74929789a90e1c35d81ac86e21225c9f844d718d8940e3b3"
},
{
"name": "wc",
"unicode": "1F6BE",
- "digest": "cb7c5d35bf11149d12cda2c0897cb6038e043127055bbe2e8e33c9b422d6d8fc"
+ "digest": "4b95d54e0b53e4b705277917653503b32d6a143c2eaf6c547bc8e01c2dc23659"
},
{
"name": "weary",
"unicode": "1F629",
- "digest": "29a291033a1b67eda3710dffae42d63fcfa663e37dab728c236172f3e877fe8f"
+ "digest": "3528f85540996cd5b562efe5421c495fc1bb414dc797bc20062783ae1b730847"
},
{
"name": "wedding",
"unicode": "1F492",
- "digest": "6c7d874f464c9c76b0d767135aa40ced94089b5f71d373098b47488d7f3ef7c4"
+ "digest": "980f3522cc4c19c3096e668032ea2cd19e7900cdc4b73bbb1c9b4c4d28dc78af"
},
{
"name": "whale",
"unicode": "1F433",
- "digest": "94168acda6ba502b64ea50ff4aaafb7e6258d7c6806e91f090c8a3c46edc5b6d"
+ "digest": "6368fe4bc4a7f68aa2bd5386686a5f1b159feacbec16d59515f2b6e5d01adfbd"
},
{
"name": "whale2",
"unicode": "1F40B",
- "digest": "e1cde2308bd510b2449c96e88ffec796856f98b19ceedc1cd7e9ea009dae1417"
+ "digest": "ccd3edf88167965f2abc18631ffb80e2532f728da35bc0c11144376685da18e8"
},
{
"name": "wheel_of_dharma",
"unicode": "2638",
- "digest": "bbd6927697c22a1c3e56fd0c9933d9e00dbf120505fe48d02cb486bcd67a8b2c"
+ "digest": "4a0a13fcd507b9621686c8090bf340aa8770c064e0e3eb576fbae1229000d6da"
},
{
"name": "wheelchair",
"unicode": "267F",
- "digest": "513f759acf528f6a7e39d9de1d171c3faebe645c9cf3bd86b185123016beef95"
+ "digest": "f5250f2b4b5b4ffe6a6f77d30865c3f5d7173fc91aee547869589b2a96da91c8"
},
{
"name": "white_check_mark",
"unicode": "2705",
- "digest": "a0b3bf7c4fb131e7a9fab5169ea4094e2665e02cedaa091f0d6e78609b2f17ed"
+ "digest": "45eb17bde6e503f22c8579d6e4d507ad6557a15f9eaad14aa716ec9ba1540876"
},
{
"name": "white_circle",
@@ -10857,142 +10857,142 @@
{
"name": "white_flower",
"unicode": "1F4AE",
- "digest": "a3efea4950e09994f5e9d3d16f0728969238302304a6cce90b293c56e9a3e20c"
+ "digest": "ace093b310eeefdecf4a4bdaf4fbcbb568457b0191ac80778a466ac5f3f4025a"
},
{
"name": "white_large_square",
"unicode": "2B1C",
- "digest": "99c4442a65f2e3c568f45aed9e74590206c517a716557f4d741d967c9f42ed40"
+ "digest": "0db6957ee9ff7325b534b730fc05345a63d4ed9060f0f816807d0dcf004baa3e"
},
{
"name": "white_medium_small_square",
"unicode": "25FD",
- "digest": "a1edfeb4e540dcc020ba5dde19f7a18d90966788baa5382a22a0f9038d593f01"
+ "digest": "d79689981a7b38211c60a025a81e44fd39ac6ea4062e227cae3aab8f51572cd4"
},
{
"name": "white_medium_square",
"unicode": "25FB",
- "digest": "794c2339ca71bb6d65ac488fb7b5dc4f0a2412f30890d2c4ece53cdbf52ba78b"
+ "digest": "6c4ce26d3f69667219f29ea18b04f3e79373024426275f25936e09a683e9a4fc"
},
{
"name": "white_small_square",
"unicode": "25AB",
- "digest": "9c4c308070a0c4524993cc36feaa778aad8f0df9f209b82d28b1f3811c441bc4"
+ "digest": "ae0d35a6bbba4592b89b2f0f1f2d183efb2f93cf2a2136c0c195aab72f0bb1c8"
},
{
"name": "white_square_button",
"unicode": "1F533",
- "digest": "f46e18c7250c874d1b4d6117eda741d86a081352e76f3d019dd64af2669fa4bb"
+ "digest": "797f3d9e44e88e940ffc118e52d0f709eec2ef14b13bdf873ad4b0c96cc0b042"
},
{
"name": "white_sun_cloud",
"unicode": "1F325",
- "digest": "d8ce416e6bdb0e59e06e2fceac3177dbe59fefc248fd8c6d76b80d1418141070"
+ "digest": "0e714038bb0a5b091dd4ad8829c5c72dece493e09da6d56ceadcd0b68e1c0fd5"
},
{
"name": "white_sun_behind_cloud",
"unicode": "1F325",
- "digest": "d8ce416e6bdb0e59e06e2fceac3177dbe59fefc248fd8c6d76b80d1418141070"
+ "digest": "0e714038bb0a5b091dd4ad8829c5c72dece493e09da6d56ceadcd0b68e1c0fd5"
},
{
"name": "white_sun_rain_cloud",
"unicode": "1F326",
- "digest": "d2b132518261864ac4a95707eaeea335dd8351ed2b8ef4e2272ced456e309bf1"
+ "digest": "82fb2a91d43c7c511afed216e12f98e32aef4475e7f3c7ccc0f39732d2f7d5e5"
},
{
"name": "white_sun_behind_cloud_with_rain",
"unicode": "1F326",
- "digest": "d2b132518261864ac4a95707eaeea335dd8351ed2b8ef4e2272ced456e309bf1"
+ "digest": "82fb2a91d43c7c511afed216e12f98e32aef4475e7f3c7ccc0f39732d2f7d5e5"
},
{
"name": "white_sun_small_cloud",
"unicode": "1F324",
- "digest": "b86a72f1cdb4d24fd3ab180aae9db012ca51fc01f3786aab596c2e330066b185"
+ "digest": "0a6164cdadf2413555b7ef47b95f823f5a010f36d2dacfb1a38335a0f59e9601"
},
{
"name": "white_sun_with_small_cloud",
"unicode": "1F324",
- "digest": "b86a72f1cdb4d24fd3ab180aae9db012ca51fc01f3786aab596c2e330066b185"
+ "digest": "0a6164cdadf2413555b7ef47b95f823f5a010f36d2dacfb1a38335a0f59e9601"
},
{
"name": "wind_blowing_face",
"unicode": "1F32C",
- "digest": "20bdeb8e39dc637792ac9fbee031c5791889f3126e83556ba51f98809c19763c"
+ "digest": "e4f63149cbc8829118571f6a93487b96d26665fc15d17d578cca4e5c752cd54f"
},
{
"name": "wind_chime",
"unicode": "1F390",
- "digest": "1fc26f33ce13b6a969bb76e914de054ec5d1c7c4cd1dc5ee8fea5f3149f794d8"
+ "digest": "1b1b212fbd74a9edc62aee7ffab9bcf91d3a9f69bffb2be4b7fd527914c14ced"
},
{
"name": "wine_glass",
"unicode": "1F377",
- "digest": "7dfcf9c5195a20fd2745b19e102910392b0fc8f1650b98ab81957807841935e0"
+ "digest": "d99107d6809386bc5e219aa58ee4930d27b7c3a6d2b10deb9f523df369f766d1"
},
{
"name": "wink",
"unicode": "1F609",
- "digest": "404ac6c920414ca35894da1d97b3b2fabe92bd09569274eb5798fbb297129036"
+ "digest": "56e29994a47335a901d0c98fa141d26faae8f647a860517bd3615fa980921885"
},
{
"name": "wolf",
"unicode": "1F43A",
- "digest": "ebadd7766c4a314b4027c32435a2f5727a6283123dfb8834e10251cbfc07ca2f"
+ "digest": "4a983f5ec8ec0872fcde7890e17605b1229064e5e194b6fca1c4259068d1caed"
},
{
"name": "woman",
"unicode": "1F469",
- "digest": "9f0dbb5d1e0db4f008141582dcb6413f5aebaa13e191349c976a435b2bee0956"
+ "digest": "a06a22a48eeb3aeb885321358fe234e97797ed33be17f52d232ce2830cfbcd97"
},
{
"name": "woman_tone1",
"unicode": "1F469-1F3FB",
- "digest": "c1f2a503481fdd96cfbfa7d556500f8e0da0cea1c72ed1078ecbb6962221c22a"
+ "digest": "c2e4b135c1dac6a0b002569a6ccd9d098f6cb18481c68b5d9115e11241a0978d"
},
{
"name": "woman_tone2",
"unicode": "1F469-1F3FC",
- "digest": "bf78b3a8f7424037069f8ac337e154ef185f55026c71a6cf6dbe15eb42ef9813"
+ "digest": "4848e650051214a53c4cd9f6d3d94158f77f65ecb34f891789de34ee0a713006"
},
{
"name": "woman_tone3",
"unicode": "1F469-1F3FD",
- "digest": "4ccd70a2052b932b3395ac0a957c05815327dc8082fd461abcd797411db8ce05"
+ "digest": "b6f751ad47da019cdfb9d6d78f9610adb92120abf204c30df79a9150b57dbdee"
},
{
"name": "woman_tone4",
"unicode": "1F469-1F3FE",
- "digest": "71b5efc4a410102e60048ca05f87587384a6db309f3be94109a4f92ea97072dc"
+ "digest": "fd27d3a669dc34313fbfe518df7dc2ded3ade5dde695f8d773afe87bf8a8b0d4"
},
{
"name": "woman_tone5",
"unicode": "1F469-1F3FF",
- "digest": "91a1cd015731f4db501c276a8236eb0665e4dc7aa1891e2a67b8d3e543fbea9c"
+ "digest": "9ae9b14dfff40fa60a565d89479727feeba4fd6ffea9acb353a81b14aba751d4"
},
{
"name": "womans_clothes",
"unicode": "1F45A",
- "digest": "599332c0b863a40fd0c319e4e0f52ae847326a96d180c288e0466b3ac308a27e"
+ "digest": "d12a27810780fe5cd8118ed4587e0c4e70dbe9bcd014c6866fe6a8c9c7c55698"
},
{
"name": "womans_hat",
"unicode": "1F452",
- "digest": "231ff55c3fa56d8fb5731fe41f547e67ffacfdde82286f45d4ca65a2d2821239"
+ "digest": "52a0255b3483085bd125d39b74516ab6a81003964f44995c2fac821e7ff93086"
},
{
"name": "womens",
"unicode": "1F6BA",
- "digest": "f971429456b543804412490af2e27e0b14d0d536a156db898bce67b136e1b563"
+ "digest": "7e38964006f8b28dfa2b3e9b2b16553bb50c18a63455f556b0bff35ee172137e"
},
{
"name": "worried",
"unicode": "1F61F",
- "digest": "e017f636e79b9301f3a06471a5f3513ba7dbb9b97938de1140c1df4c32fd8844"
+ "digest": "5a073985e1344bc34201ef94a491f7f2b946f5828c9fdbc57eeb2dcd87ac3a6b"
},
{
"name": "wrench",
"unicode": "1F527",
- "digest": "c9ded4f7f496bad8691677226310bbd31bb485722ea479bc7a68a2b4ef9d55d9"
+ "digest": "81aae53bc892035b905bf3ec5b442a8ecc95027c5fa9eb51b7c3e7d8fad3f3f4"
},
{
"name": "writing_hand",
@@ -11007,76 +11007,76 @@
{
"name": "writing_hand_tone1",
"unicode": "270D-1F3FB",
- "digest": "38e64e6dca4847a12aef8a117c113b2025d841501c4bc8188c57d0c8a4f1e34d"
+ "digest": "2c7e2108e1990490b681343c1b01b4183d4f18fbdef792f113b2f87595e0dad0"
},
{
"name": "writing_hand_tone2",
"unicode": "270D-1F3FC",
- "digest": "2b2d0ac2701ae707c31d9c85feb2e3700e11398701e2b0519338897817d53baf"
+ "digest": "87ec8d44f472d301adbcbd50d8c852b609e46584057f59cc1527401db363c1bf"
},
{
"name": "writing_hand_tone3",
"unicode": "270D-1F3FD",
- "digest": "85d67f90ff8bd2e7157f28fd857e6730b660a7eb82eb5350f57671f728ce725b"
+ "digest": "4a48ddef91f7264e8fa9cca223554db22b3a2e3153e94b88d146644ea6dd661e"
},
{
"name": "writing_hand_tone4",
"unicode": "270D-1F3FE",
- "digest": "056c05c201b3d0972433f00910967ad7334e37726e2956fee053ec2e1a9153c7"
+ "digest": "e5254564a1f91e42ee59f359d8cd26f52abdc04dca8f3b37cb2f140cb7f71390"
},
{
"name": "writing_hand_tone5",
"unicode": "270D-1F3FF",
- "digest": "95c59157d301ee08990e4302fd9bdd7953e1d1abed09636d0837d84e44f53ba6"
+ "digest": "61299bf86d83d323ca3e6052c535ae66c6f7b3d9866a37db0464223b8bc28523"
},
{
"name": "x",
"unicode": "274C",
- "digest": "1d256b0015b9cbdeaa4558f9241782c89d86c79a42e507621f7949c56a90b6c0"
+ "digest": "3e5a7918e31ddefdf1ce73972365e2f0bfd2917d6a450c1a278c108349c9425d"
},
{
"name": "yellow_heart",
"unicode": "1F49B",
- "digest": "e869a80266b4379a8d82988fef25e187632bfb076ae619f576e416906cd688a7"
+ "digest": "a1098f2f04c29754cc9974324508386787d4d803b57cf691d42de414cb2679d6"
},
{
"name": "yen",
"unicode": "1F4B4",
- "digest": "8f3d801c687e585e4497123c5c91a8b0c558578deec6a8c1591b25e64a3a8992"
+ "digest": "944daaeb3f6369c807c0e63b106cee1360040f7800a70c0d942a992f25a55da7"
},
{
"name": "yin_yang",
"unicode": "262F",
- "digest": "e8ea4c686518ad6165e15ed67b529f2f1e20d648aa2ecb7e9bff5a6067dd3fea"
+ "digest": "5ee8d13dacf41306a09237bfcff6abeef110331b40eb7d6e80600628c1327545"
},
{
"name": "yum",
"unicode": "1F60B",
- "digest": "d9c97bbf6bdb6e39977437680f0b37c9335306c51e01114056ae1d4c9c85b0e0"
+ "digest": "31a89088c21bd7a74a3a26d731a907d1bc49436300a9f9c55248703cf7ef44c7"
},
{
"name": "zap",
"unicode": "26A1",
- "digest": "37588734c7fe330ae35e6ee99e7cf4183e8fe1bc01f6bbbc6293b21076a338cb"
+ "digest": "9f8144ae6f866129aea41bbf694b0c858ef9352a139969e57cd8db73385f52c3"
},
{
"name": "zero",
"unicode": "0030-20E3",
- "digest": "519c927db8264d5379ab2c6a18656ea6dd1ceb2afc92eb48563bf86af4697571"
+ "digest": "1b27b5c904defadbdd28ace67a6be5c277ff043297db7cd9f672bbf84e37fa1a"
},
{
"name": "zipper_mouth",
"unicode": "1F910",
- "digest": "8396249161b6d865861b56aabd17cae2c821b0d814f4249bf8cab0bb21fa8ee9"
+ "digest": "81bee5aa1202dfd5a4c7badb71ec0e44b8f75c2cbef94e6fd35c593d8770ae43"
},
{
"name": "zipper_mouth_face",
"unicode": "1F910",
- "digest": "8396249161b6d865861b56aabd17cae2c821b0d814f4249bf8cab0bb21fa8ee9"
+ "digest": "81bee5aa1202dfd5a4c7badb71ec0e44b8f75c2cbef94e6fd35c593d8770ae43"
},
{
"name": "zzz",
"unicode": "1F4A4",
- "digest": "f07c56d2d55c0a886c26a8e3d49a9adeab54cc1a0c0354ea8d3bf23aaed3176d"
+ "digest": "b3313d0c44a59fa9d4ce9f7eb4d07ff71dfc8bb01798154250f27cdcf3c693b5"
}
] \ No newline at end of file
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 8cba77b148a..b62afb4bb4c 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -59,6 +59,14 @@ module API
expose :path, :path_with_namespace
end
+ class SharedGroup < Grape::Entity
+ expose :group_id
+ expose :group_name do |group_link, options|
+ group_link.group.name
+ end
+ expose :group_access, as: :group_access_level
+ end
+
class Project < Grape::Entity
expose :id, :description, :default_branch, :tag_list
expose :public?, as: :public
@@ -78,6 +86,9 @@ module API
expose :open_issues_count, if: lambda { |project, options| project.issues_enabled? && project.default_issues_tracker? }
expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] }
expose :public_builds
+ expose :shared_with_groups do |project, options|
+ SharedGroup.represent(project.project_group_links.all, options)
+ end
end
class ProjectMember < UserBasic
@@ -94,6 +105,7 @@ module API
class GroupDetail < Group
expose :projects, using: Entities::Project
+ expose :shared_projects, using: Entities::Project
end
class GroupMember < UserBasic
@@ -188,7 +200,6 @@ module API
expose :author, :assignee, using: Entities::UserBasic
expose :source_project_id, :target_project_id
expose :label_names, as: :labels
- expose :description
expose :work_in_progress?, as: :work_in_progress
expose :milestone, using: Entities::Milestone
expose :merge_when_build_succeeds
@@ -197,6 +208,8 @@ module API
merge_request.subscribed?(options[:current_user])
end
expose :user_notes_count
+ expose :should_remove_source_branch?, as: :should_remove_source_branch
+ expose :force_remove_source_branch?, as: :force_remove_source_branch
end
class MergeRequestChanges < MergeRequest
@@ -241,9 +254,9 @@ module API
class CommitNote < Grape::Entity
expose :note
- expose(:path) { |note| note.diff_file_path if note.legacy_diff_note? }
- expose(:line) { |note| note.diff_new_line if note.legacy_diff_note? }
- expose(:line_type) { |note| note.diff_line_type if note.legacy_diff_note? }
+ expose(:path) { |note| note.diff_file.try(:file_path) if note.diff_note? }
+ expose(:line) { |note| note.diff_line.try(:new_line) if note.diff_note? }
+ expose(:line_type) { |note| note.diff_line.try(:type) if note.diff_note? }
expose :author, using: Entities::UserBasic
expose :created_at
end
diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index b32503e8516..d5dfba5e0cc 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -13,6 +13,7 @@ module API
# action - git action (git-upload-pack or git-receive-pack)
# ref - branch name
# forced_push - forced_push
+ # protocol - Git access protocol being used, e.g. HTTP or SSH
#
helpers do
@@ -46,11 +47,13 @@ module API
User.find_by(id: params[:user_id])
end
+ protocol = params[:protocol]
+
access =
if wiki?
- Gitlab::GitAccessWiki.new(actor, project)
+ Gitlab::GitAccessWiki.new(actor, project, protocol)
else
- Gitlab::GitAccess.new(actor, project)
+ Gitlab::GitAccess.new(actor, project, protocol)
end
access_status = access.check(params[:action], params[:changes])
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 0e94efd4acd..4fcdf8968c9 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -233,8 +233,8 @@ module API
render_api_error!('Branch cannot be merged', 406) unless merge_request.mergeable?
- if params[:sha] && merge_request.source_sha != params[:sha]
- render_api_error!("SHA does not match HEAD of source branch: #{merge_request.source_sha}", 409)
+ if params[:sha] && merge_request.diff_head_sha != params[:sha]
+ render_api_error!("SHA does not match HEAD of source branch: #{merge_request.diff_head_sha}", 409)
end
merge_params = {
diff --git a/lib/banzai/filter/blockquote_fence_filter.rb b/lib/banzai/filter/blockquote_fence_filter.rb
new file mode 100644
index 00000000000..d2c4b1e4d76
--- /dev/null
+++ b/lib/banzai/filter/blockquote_fence_filter.rb
@@ -0,0 +1,71 @@
+module Banzai
+ module Filter
+ class BlockquoteFenceFilter < HTML::Pipeline::TextFilter
+ REGEX = %r{
+ (?<code>
+ # Code blocks:
+ # ```
+ # Anything, including `>>>` blocks which are ignored by this filter
+ # ```
+
+ ^```
+ .+?
+ \n```$
+ )
+ |
+ (?<html>
+ # HTML block:
+ # <tag>
+ # Anything, including `>>>` blocks which are ignored by this filter
+ # </tag>
+
+ ^<[^>]+?>\n
+ .+?
+ \n<\/[^>]+?>$
+ )
+ |
+ (?:
+ # Blockquote:
+ # >>>
+ # Anything, including code and HTML blocks
+ # >>>
+
+ ^>>>\n
+ (?<quote>
+ (?:
+ # Any character that doesn't introduce a code or HTML block
+ (?!
+ ^```
+ |
+ ^<[^>]+?>\n
+ )
+ .
+ |
+ # A code block
+ \g<code>
+ |
+ # An HTML block
+ \g<html>
+ )+?
+ )
+ \n>>>$
+ )
+ }mx.freeze
+
+ def initialize(text, context = nil, result = nil)
+ super text, context, result
+ @text = @text.delete("\r")
+ end
+
+ def call
+ @text.gsub(REGEX) do
+ if $~[:quote]
+ $~[:quote].gsub(/^/, "> ").gsub(/^> $/, ">")
+ else
+ $~[0]
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/emoji_filter.rb b/lib/banzai/filter/emoji_filter.rb
index d25de900674..ae7d31cf191 100644
--- a/lib/banzai/filter/emoji_filter.rb
+++ b/lib/banzai/filter/emoji_filter.rb
@@ -61,7 +61,7 @@ module Banzai
# Build a regexp that matches all valid :emoji: names.
def self.emoji_pattern
- @emoji_pattern ||= /:(#{Emoji.emojis_names.map { |name| Regexp.escape(name) }.join('|')}):/
+ @emoji_pattern ||= /:(#{Gitlab::Emoji.emojis_names.map { |name| Regexp.escape(name) }.join('|')}):/
end
def emoji_pattern
@@ -69,7 +69,7 @@ module Banzai
end
def emoji_filename(name)
- "#{Emoji.emoji_filename(name)}.png"
+ "#{Gitlab::Emoji.emoji_filename(name)}.png"
end
end
end
diff --git a/lib/banzai/filter/label_reference_filter.rb b/lib/banzai/filter/label_reference_filter.rb
index e4d3f87d0aa..e258dc8e2bf 100644
--- a/lib/banzai/filter/label_reference_filter.rb
+++ b/lib/banzai/filter/label_reference_filter.rb
@@ -13,13 +13,13 @@ module Banzai
end
def self.references_in(text, pattern = Label.reference_pattern)
- text.gsub(pattern) do |match|
+ unescape_html_entities(text).gsub(pattern) do |match|
yield match, $~[:label_id].to_i, $~[:label_name], $~[:project], $~
end
end
def references_in(text, pattern = Label.reference_pattern)
- text.gsub(pattern) do |match|
+ unescape_html_entities(text).gsub(pattern) do |match|
label = find_label($~[:project], $~[:label_id], $~[:label_name])
if label
@@ -66,6 +66,10 @@ module Banzai
LabelsHelper.render_colored_cross_project_label(object)
end
end
+
+ def unescape_html_entities(text)
+ CGI.unescapeHTML(text.to_s)
+ end
end
end
end
diff --git a/lib/banzai/object_renderer.rb b/lib/banzai/object_renderer.rb
index f0e4f28bf12..dc83b87a6c1 100644
--- a/lib/banzai/object_renderer.rb
+++ b/lib/banzai/object_renderer.rb
@@ -31,10 +31,10 @@ module Banzai
redacted = redact_documents(documents)
objects.each_with_index do |object, index|
- object.__send__("#{attribute}_html=", redacted.fetch(index))
+ redacted_data = redacted[index]
+ object.__send__("#{attribute}_html=", redacted_data[:document].to_html.html_safe)
+ object.user_visible_reference_count = redacted_data[:visible_reference_count]
end
-
- objects
end
# Renders the attribute of every given object.
@@ -50,9 +50,7 @@ module Banzai
def redact_documents(documents)
redactor = Redactor.new(project, user)
- redactor.redact(documents).map do |document|
- document.to_html.html_safe
- end
+ redactor.redact(documents)
end
# Returns a Banzai context for the given object and attribute.
diff --git a/lib/banzai/pipeline/pre_process_pipeline.rb b/lib/banzai/pipeline/pre_process_pipeline.rb
index 50dc978b452..6cf219661d3 100644
--- a/lib/banzai/pipeline/pre_process_pipeline.rb
+++ b/lib/banzai/pipeline/pre_process_pipeline.rb
@@ -3,7 +3,8 @@ module Banzai
class PreProcessPipeline < BasePipeline
def self.filters
FilterArray[
- Filter::YamlFrontMatterFilter
+ Filter::YamlFrontMatterFilter,
+ Filter::BlockquoteFenceFilter,
]
end
diff --git a/lib/banzai/redactor.rb b/lib/banzai/redactor.rb
index ffd267d5e9a..0df3a72d1c4 100644
--- a/lib/banzai/redactor.rb
+++ b/lib/banzai/redactor.rb
@@ -19,29 +19,36 @@ module Banzai
#
# Returns the documents passed as the first argument.
def redact(documents)
- nodes = documents.flat_map do |document|
- Querying.css(document, 'a.gfm[data-reference-type]')
- end
-
- redact_nodes(nodes)
+ all_document_nodes = document_nodes(documents)
- documents
+ redact_document_nodes(all_document_nodes)
end
- # Redacts the given nodes
+ # Redacts the given node documents
#
- # nodes - An Array of HTML nodes to redact.
- def redact_nodes(nodes)
- visible = nodes_visible_to_user(nodes)
+ # data - An Array of a Hashes mapping an HTML document to nodes to redact.
+ def redact_document_nodes(all_document_nodes)
+ all_nodes = all_document_nodes.map { |x| x[:nodes] }.flatten
+ visible = nodes_visible_to_user(all_nodes)
+ metadata = []
- nodes.each do |node|
- unless visible.include?(node)
+ all_document_nodes.each do |entry|
+ nodes_for_document = entry[:nodes]
+ doc_data = { document: entry[:document], visible_reference_count: nodes_for_document.count }
+ metadata << doc_data
+
+ nodes_for_document.each do |node|
+ next if visible.include?(node)
+
+ doc_data[:visible_reference_count] -= 1
# The reference should be replaced by the original text,
# which is not always the same as the rendered text.
text = node.attr('data-original') || node.text
node.replace(text)
end
end
+
+ metadata
end
# Returns the nodes visible to the current user.
@@ -65,5 +72,11 @@ module Banzai
visible
end
+
+ def document_nodes(documents)
+ documents.map do |document|
+ { document: document, nodes: Querying.css(document, 'a.gfm[data-reference-type]') }
+ end
+ end
end
end
diff --git a/lib/banzai/reference_parser/base_parser.rb b/lib/banzai/reference_parser/base_parser.rb
index 3d7b9c4a024..6cf218aaa0d 100644
--- a/lib/banzai/reference_parser/base_parser.rb
+++ b/lib/banzai/reference_parser/base_parser.rb
@@ -133,8 +133,9 @@ module Banzai
return {} if nodes.empty?
ids = unique_attribute_values(nodes, attribute)
+ rows = collection_objects_for_ids(collection, ids)
- collection.where(id: ids).each_with_object({}) do |row, hash|
+ rows.each_with_object({}) do |row, hash|
hash[row.id] = row
end
end
@@ -153,6 +154,31 @@ module Banzai
values.to_a
end
+ # Queries the collection for the objects with the given IDs.
+ #
+ # If the RequestStore module is enabled this method will only query any
+ # 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?
+ cache = collection_cache[collection_cache_key(collection)]
+ to_query = ids.map(&:to_i) - cache.keys
+
+ unless to_query.empty?
+ collection.where(id: to_query).each { |row| cache[row.id] = row }
+ end
+
+ cache.values
+ else
+ collection.where(id: ids)
+ end
+ end
+
+ # Returns the cache key to use for a collection.
+ def collection_cache_key(collection)
+ collection.respond_to?(:model) ? collection.model : collection
+ end
+
# Processes the list of HTML documents and returns an Array containing all
# the references.
def process(documents)
@@ -189,7 +215,7 @@ module Banzai
end
def find_projects_for_hash_keys(hash)
- Project.where(id: hash.keys)
+ collection_objects_for_ids(Project, hash.keys)
end
private
@@ -199,6 +225,12 @@ module Banzai
def lazy(&block)
Gitlab::Lazy.new(&block)
end
+
+ def collection_cache
+ RequestStore[:banzai_collection_cache] ||= Hash.new do |hash, key|
+ hash[key] = {}
+ end
+ end
end
end
end
diff --git a/lib/banzai/reference_parser/user_parser.rb b/lib/banzai/reference_parser/user_parser.rb
index a12b0d19560..863f5725d3b 100644
--- a/lib/banzai/reference_parser/user_parser.rb
+++ b/lib/banzai/reference_parser/user_parser.rb
@@ -73,7 +73,7 @@ module Banzai
def find_users(ids)
return [] if ids.empty?
- User.where(id: ids).to_a
+ collection_objects_for_ids(User, ids)
end
def find_users_for_groups(ids)
@@ -85,7 +85,8 @@ module Banzai
def find_users_for_projects(ids)
return [] if ids.empty?
- Project.where(id: ids).flat_map { |p| p.team.members.to_a }
+ collection_objects_for_ids(Project, ids).
+ flat_map { |p| p.team.members.to_a }
end
end
end
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index 54b46e5d23f..ffc1814b29d 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -48,6 +48,7 @@ module Gitlab
akismet_enabled: false,
repository_checks_enabled: true,
container_registry_token_expire_delay: 5,
+ user_default_external: false,
)
end
diff --git a/lib/gitlab/diff/diff_refs.rb b/lib/gitlab/diff/diff_refs.rb
new file mode 100644
index 00000000000..8406ca4269c
--- /dev/null
+++ b/lib/gitlab/diff/diff_refs.rb
@@ -0,0 +1,36 @@
+module Gitlab
+ module Diff
+ class DiffRefs
+ attr_reader :base_sha
+ attr_reader :start_sha
+ attr_reader :head_sha
+
+ def initialize(base_sha:, start_sha: base_sha, head_sha:)
+ @base_sha = base_sha
+ @start_sha = start_sha
+ @head_sha = head_sha
+ end
+
+ def ==(other)
+ other.is_a?(self.class) &&
+ base_sha == other.base_sha &&
+ start_sha == other.start_sha &&
+ head_sha == other.head_sha
+ end
+
+ # There is only one case in which we will have `start_sha` and `head_sha`,
+ # but not `base_sha`, which is when a diff is generated between an
+ # orphaned branch and another branch, which means there _is_ no base, but
+ # we're still able to highlight it, and to create diff notes, which are
+ # the primary things `DiffRefs` are used for.
+ # `DiffRefs` are "complete" when they have `start_sha` and `head_sha`,
+ # because `base_sha` can always be derived from this, to return an actual
+ # sha, or `nil`.
+ # We have `base_sha` directly available on `DiffRefs` because it's faster#
+ # than having to look it up in the repo every time.
+ def complete?
+ start_sha && head_sha
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb
index d2e85cabf72..7e01f7b61fb 100644
--- a/lib/gitlab/diff/file.rb
+++ b/lib/gitlab/diff/file.rb
@@ -1,47 +1,87 @@
module Gitlab
module Diff
class File
- attr_reader :diff, :diff_refs
+ attr_reader :diff, :repository, :diff_refs
delegate :new_file, :deleted_file, :renamed_file,
- :old_path, :new_path, to: :diff, prefix: false
+ :old_path, :new_path, :a_mode, :b_mode,
+ :submodule?, :too_large?, to: :diff, prefix: false
- def initialize(diff, diff_refs)
+ def initialize(diff, repository:, diff_refs: nil)
@diff = diff
+ @repository = repository
@diff_refs = diff_refs
end
+ def position(line)
+ return unless diff_refs
+
+ Position.new(
+ old_path: old_path,
+ new_path: new_path,
+ old_line: line.old_line,
+ new_line: line.new_line,
+ diff_refs: diff_refs
+ )
+ end
+
+ def line_code(line)
+ return if line.meta?
+
+ Gitlab::Diff::LineCode.generate(file_path, line.new_pos, line.old_pos)
+ end
+
+ def line_for_line_code(code)
+ diff_lines.find { |line| line_code(line) == code }
+ end
+
+ def line_for_position(pos)
+ diff_lines.find { |line| position(line) == pos }
+ end
+
+ def position_for_line_code(code)
+ line = line_for_line_code(code)
+ position(line) if line
+ end
+
+ def line_code_for_position(pos)
+ line = line_for_position(pos)
+ line_code(line) if line
+ end
+
+ def content_commit
+ return unless diff_refs
+
+ repository.commit(deleted_file ? old_ref : new_ref)
+ end
+
def old_ref
- diff_refs[0] if diff_refs
+ diff_refs.try(:base_sha)
end
def new_ref
- diff_refs[1] if diff_refs
+ diff_refs.try(:head_sha)
end
- # Array of Gitlab::DIff::Line objects
+ # Array of Gitlab::Diff::Line objects
def diff_lines
- @lines ||= parser.parse(raw_diff.each_line).to_a
+ @lines ||= Gitlab::Diff::Parser.new.parse(raw_diff.each_line).to_a
end
- def too_large?
- diff.too_large?
+ def collapsed_by_default?
+ diff.diff.bytesize > 10240 # 10 KB
end
def highlighted_diff_lines
- Gitlab::Diff::Highlight.new(self).highlight
+ @highlighted_diff_lines ||= Gitlab::Diff::Highlight.new(self, repository: self.repository).highlight
end
def parallel_diff_lines
- Gitlab::Diff::ParallelDiff.new(self).parallelize
+ @parallel_diff_lines ||= Gitlab::Diff::ParallelDiff.new(self).parallelize
end
def mode_changed?
- !!(diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode)
- end
-
- def parser
- Gitlab::Diff::Parser.new
+ a_mode && b_mode && a_mode != b_mode
end
def raw_diff
@@ -53,17 +93,15 @@ module Gitlab
end
def prev_line(index)
- if index > 0
- diff_lines[index - 1]
- end
+ diff_lines[index - 1] if index > 0
+ end
+
+ def paths
+ [old_path, new_path].compact
end
def file_path
- if diff.new_path.present?
- diff.new_path
- elsif diff.old_path.present?
- diff.old_path
- end
+ new_path.presence || old_path
end
def added_lines
@@ -73,6 +111,21 @@ module Gitlab
def removed_lines
diff_lines.count(&:removed?)
end
+
+ def old_blob(commit = content_commit)
+ return unless commit
+
+ parent_id = commit.parent_id
+ return unless parent_id
+
+ repository.blob_at(parent_id, old_path)
+ end
+
+ def blob(commit = content_commit)
+ return unless commit
+
+ repository.blob_at(commit.id, file_path)
+ end
end
end
end
diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb
index 9429b3ff88d..649a265a02c 100644
--- a/lib/gitlab/diff/highlight.rb
+++ b/lib/gitlab/diff/highlight.rb
@@ -1,11 +1,13 @@
module Gitlab
module Diff
class Highlight
- attr_reader :diff_file, :diff_lines, :raw_lines
+ attr_reader :diff_file, :diff_lines, :raw_lines, :repository
delegate :old_path, :new_path, :old_ref, :new_ref, to: :diff_file, prefix: :diff
- def initialize(diff_lines)
+ def initialize(diff_lines, repository: nil)
+ @repository = repository
+
if diff_lines.is_a?(Gitlab::Diff::File)
@diff_file = diff_lines
@diff_lines = @diff_file.diff_lines
@@ -19,7 +21,7 @@ module Gitlab
@diff_lines.map.with_index do |diff_line, i|
diff_line = diff_line.dup
# ignore highlighting for "match" lines
- next diff_line if diff_line.type == 'match' || diff_line.type == 'nonewline'
+ next diff_line if diff_line.meta?
rich_line = highlight_line(diff_line) || diff_line.text
@@ -40,12 +42,12 @@ module Gitlab
line_prefix = diff_line.text.match(/\A(.)/) ? $1 : ' '
- case diff_line.type
- when 'new', nil
- rich_line = new_lines[diff_line.new_pos - 1]
- when 'old'
- rich_line = old_lines[diff_line.old_pos - 1]
- end
+ rich_line =
+ if diff_line.unchanged? || diff_line.added?
+ new_lines[diff_line.new_pos - 1]
+ elsif diff_line.removed?
+ old_lines[diff_line.old_pos - 1]
+ end
# Only update text if line is found. This will prevent
# issues with submodules given the line only exists in diff content.
@@ -58,19 +60,12 @@ module Gitlab
def old_lines
return unless diff_file
- @old_lines ||= Gitlab::Highlight.highlight_lines(*processing_args(:old))
+ @old_lines ||= Gitlab::Highlight.highlight_lines(self.repository, diff_old_ref, diff_old_path)
end
def new_lines
return unless diff_file
- @new_lines ||= Gitlab::Highlight.highlight_lines(*processing_args(:new))
- end
-
- def processing_args(version)
- ref = send("diff_#{version}_ref")
- path = send("diff_#{version}_path")
-
- [ref.project.repository, ref.id, path]
+ @new_lines ||= Gitlab::Highlight.highlight_lines(self.repository, diff_new_ref, diff_new_path)
end
end
end
diff --git a/lib/gitlab/diff/line.rb b/lib/gitlab/diff/line.rb
index 03730b435ad..c6189d660c2 100644
--- a/lib/gitlab/diff/line.rb
+++ b/lib/gitlab/diff/line.rb
@@ -9,6 +9,18 @@ module Gitlab
@old_pos, @new_pos = old_pos, new_pos
end
+ def old_line
+ old_pos unless added? || meta?
+ end
+
+ def new_line
+ new_pos unless removed? || meta?
+ end
+
+ def unchanged?
+ type.nil?
+ end
+
def added?
type == 'new'
end
@@ -16,6 +28,10 @@ module Gitlab
def removed?
type == 'old'
end
+
+ def meta?
+ type == 'match' || type == 'nonewline'
+ end
end
end
end
diff --git a/lib/gitlab/diff/line_mapper.rb b/lib/gitlab/diff/line_mapper.rb
new file mode 100644
index 00000000000..576a761423e
--- /dev/null
+++ b/lib/gitlab/diff/line_mapper.rb
@@ -0,0 +1,64 @@
+# 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.
+module Gitlab
+ module Diff
+ class LineMapper
+ attr_accessor :diff_file
+
+ def initialize(diff_file)
+ @diff_file = diff_file
+ end
+
+ # Find new line number for old line number.
+ def old_to_new(old_line)
+ map_line_number(old_line, from: :old_line, to: :new_line)
+ end
+
+ # Find old line number for new line number.
+ def new_to_old(new_line)
+ map_line_number(new_line, from: :new_line, to: :old_line)
+ end
+
+ private
+
+ def diff_lines
+ @diff_lines ||= @diff_file.diff_lines
+ end
+
+ # Find old/new line number based on its old/new counterpart line number.
+ def map_line_number(from_line, from:, to:)
+ # If no diff file could be found, the file wasn't changed, and the
+ # mapped line number is the same as the specified line number.
+ return from_line unless diff_file
+
+ # To find the mapped line number for the specified line number,
+ # we need to find:
+ # - The diff line with that exact line number, if it is in the diff context
+ # - The first diff line with a higher line number, if it falls between diff contexts
+ # - The last known diff line, if it falls after the last diff context
+ diff_line = diff_lines.find do |diff_line|
+ diff_from_line = diff_line.send(from)
+ diff_from_line && diff_from_line >= from_line
+ end
+ diff_line ||= diff_lines.last
+
+ # If no diff line could be found, the file wasn't changed, and the
+ # mapped line number is the same as the specified line number.
+ return from_line unless diff_line
+
+ diff_from_line = diff_line.send(from)
+ diff_to_line = diff_line.send(to)
+
+ # If the line was removed, there is no mapped line number.
+ return unless diff_to_line
+
+ # Because we may not have the diff line with the exact line number
+ # we were looking for, we need to adjust the mapped line number.
+ distance = diff_from_line - from_line
+
+ diff_to_line - distance
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/diff/parallel_diff.rb b/lib/gitlab/diff/parallel_diff.rb
index 74f9b3c050a..1c1fc148123 100644
--- a/lib/gitlab/diff/parallel_diff.rb
+++ b/lib/gitlab/diff/parallel_diff.rb
@@ -15,17 +15,19 @@ module Gitlab
highlighted_diff_lines.each do |line|
full_line = line.text
type = line.type
- line_code = generate_line_code(diff_file.file_path, line)
+ line_code = diff_file.line_code(line)
line_new = line.new_pos
line_old = line.old_pos
+ position = diff_file.position(line)
next_line = diff_file.next_line(line.index)
if next_line
next_line = highlighted_diff_lines[next_line.index]
- next_line_code = generate_line_code(diff_file.file_path, next_line)
+ full_next_line = next_line.text
+ next_line_code = diff_file.line_code(next_line)
next_type = next_line.type
- next_line = next_line.text
+ next_position = diff_file.position(next_line)
end
case type
@@ -37,12 +39,14 @@ module Gitlab
number: line_old,
text: full_line,
line_code: line_code,
+ position: position
},
right: {
type: type,
number: line_new,
text: full_line,
- line_code: line_code
+ line_code: line_code,
+ position: position
}
}
when 'old'
@@ -55,12 +59,14 @@ module Gitlab
number: line_old,
text: full_line,
line_code: line_code,
+ position: position
},
right: {
type: next_type,
number: line_new,
- text: next_line,
- line_code: next_line_code
+ text: full_next_line,
+ line_code: next_line_code,
+ position: next_position,
}
}
skip_next = true
@@ -73,12 +79,14 @@ module Gitlab
number: line_old,
text: full_line,
line_code: line_code,
+ position: position
},
right: {
type: next_type,
number: nil,
text: "",
- line_code: nil
+ line_code: nil,
+ position: nil
}
}
end
@@ -95,12 +103,14 @@ module Gitlab
number: nil,
text: "",
line_code: line_code,
+ position: position
},
right: {
type: type,
number: line_new,
text: full_line,
- line_code: line_code
+ line_code: line_code,
+ position: position
}
}
end
@@ -108,12 +118,6 @@ module Gitlab
end
lines
end
-
- private
-
- def generate_line_code(file_path, line)
- Gitlab::Diff::LineCode.generate(file_path, line.new_pos, line.old_pos)
- end
end
end
end
diff --git a/lib/gitlab/diff/position.rb b/lib/gitlab/diff/position.rb
new file mode 100644
index 00000000000..989fff8918e
--- /dev/null
+++ b/lib/gitlab/diff/position.rb
@@ -0,0 +1,155 @@
+# Defines a specific location, identified by paths and line numbers,
+# within a specific diff, identified by start, head and base commit ids.
+module Gitlab
+ module Diff
+ class Position
+ attr_reader :old_path
+ attr_reader :new_path
+ attr_reader :old_line
+ attr_reader :new_line
+ attr_reader :base_sha
+ attr_reader :start_sha
+ attr_reader :head_sha
+
+ def initialize(attrs = {})
+ @old_path = attrs[:old_path]
+ @new_path = attrs[:new_path]
+ @old_line = attrs[:old_line]
+ @new_line = attrs[:new_line]
+
+ if attrs[:diff_refs]
+ @base_sha = attrs[:diff_refs].base_sha
+ @start_sha = attrs[:diff_refs].start_sha
+ @head_sha = attrs[:diff_refs].head_sha
+ else
+ @base_sha = attrs[:base_sha]
+ @start_sha = attrs[:start_sha]
+ @head_sha = attrs[:head_sha]
+ end
+ end
+
+ # `Gitlab::Diff::Position` objects are stored as serialized attributes in
+ # `DiffNote`, which use YAML to encode and decode objects.
+ # `#init_with` and `#encode_with` can be used to customize the en/decoding
+ # behavior. In this case, we override these to prevent memoized instance
+ # variables like `@diff_file` and `@diff_line` from being serialized.
+ def init_with(coder)
+ initialize(coder['attributes'])
+
+ self
+ end
+
+ def encode_with(coder)
+ coder['attributes'] = self.to_h
+ end
+
+ def key
+ @key ||= [base_sha, start_sha, head_sha, Digest::SHA1.hexdigest(old_path || ""), Digest::SHA1.hexdigest(new_path || ""), old_line, new_line]
+ end
+
+ def ==(other)
+ other.is_a?(self.class) && key == other.key
+ end
+
+ def to_h
+ {
+ old_path: old_path,
+ new_path: new_path,
+ old_line: old_line,
+ new_line: new_line,
+ base_sha: base_sha,
+ start_sha: start_sha,
+ head_sha: head_sha
+ }
+ end
+
+ def inspect
+ %(#<#{self.class}:#{object_id} #{to_h}>)
+ end
+
+ def complete?
+ file_path.present? &&
+ (old_line || new_line) &&
+ diff_refs.complete?
+ end
+
+ def to_json
+ JSON.generate(self.to_h)
+ end
+
+ def type
+ if old_line && new_line
+ nil
+ elsif new_line
+ 'new'
+ else
+ 'old'
+ end
+ end
+
+ def unchanged?
+ type.nil?
+ end
+
+ def added?
+ type == 'new'
+ end
+
+ def removed?
+ type == 'old'
+ end
+
+ def paths
+ [old_path, new_path].compact.uniq
+ end
+
+ def file_path
+ new_path.presence || old_path
+ end
+
+ def diff_refs
+ @diff_refs ||= DiffRefs.new(base_sha: base_sha, start_sha: start_sha, head_sha: head_sha)
+ end
+
+ def diff_file(repository)
+ @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
+ end
+ end
+
+ def diff_line(repository)
+ @diff_line ||= diff_file(repository).line_for_position(self)
+ end
+
+ def line_code(repository)
+ @line_code ||= diff_file(repository).line_code_for_position(self)
+ end
+
+ private
+
+ def find_diff_file(repository)
+ diffs = Gitlab::Git::Compare.new(
+ repository.raw_repository,
+ start_sha,
+ head_sha
+ ).diffs(paths: paths)
+
+ diff = diffs.first
+ return unless diff
+
+ Gitlab::Diff::File.new(diff, repository: repository, diff_refs: diff_refs)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/diff/position_tracer.rb b/lib/gitlab/diff/position_tracer.rb
new file mode 100644
index 00000000000..4d04f867268
--- /dev/null
+++ b/lib/gitlab/diff/position_tracer.rb
@@ -0,0 +1,168 @@
+# 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
+ module Diff
+ class PositionTracer
+ attr_accessor :repository
+ attr_accessor :old_diff_refs
+ attr_accessor :new_diff_refs
+ attr_accessor :paths
+
+ def initialize(repository:, old_diff_refs:, new_diff_refs:, paths: nil)
+ @repository = repository
+ @old_diff_refs = old_diff_refs
+ @new_diff_refs = new_diff_refs
+ @paths = paths
+ end
+
+ def trace(old_position)
+ return unless old_diff_refs.complete? && new_diff_refs.complete?
+ return unless old_position.diff_refs == old_diff_refs
+
+ # Suppose we have an MR with source branch `feature` and target branch `master`.
+ # When the MR was created, the head of `master` was commit A, and the
+ # 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,
+ # 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
+ # is updated, we need to find out what line in C->D corresponds to the
+ # line the note was originally created on, so that we can update the diff note's
+ # records and continue to display it in the right place in the diffs.
+ # If we cannot find this line in the new diff, this means the diff note is now
+ # outdated, and we will display that fact to the user.
+ #
+ # In the new diff, the file the diff note was originally created on may
+ # have been renamed, deleted or even created, if the file existed in A and B,
+ # but was removed in C, and restored in D.
+ #
+ # Every diff note stores a Position object that defines a specific location,
+ # identified by paths and line numbers, within a specific diff, identified
+ # by start, head and base commit ids.
+ #
+ # For diff notes for diff A->B, the position looks like this:
+ # Position
+ # base_sha - ID of commit A
+ # head_sha - ID of commit B
+ # old_path - path as of A (nil if file was newly created)
+ # new_path - path as of B (nil if file was deleted)
+ # old_line - line number as of A (nil if file was newly created)
+ # new_line - line number as of B (nil if file was deleted)
+ #
+ # We can easily update `base_sha` and `head_sha` to hold the IDs of commits C and D,
+ # but need to find the paths and line numbers as of C and D.
+ #
+ # If the file was unchanged or newly created in A->B, the path as of D can be found
+ # by generating diff B->D ("head to head"), finding the diff file with
+ # `diff_file.old_path == position.new_path`, and taking `diff_file.new_path`.
+ # The path as of C can be found by taking diff C->D, finding the diff file
+ # with that same `new_path` and taking `diff_file.old_path`.
+ # The line number as of D can be found by using the LineMapper on diff B->D
+ # and providing the line number as of B.
+ # The line number as of C can be found by using the LineMapper on diff C->D
+ # and providing the line number as of D.
+ #
+ # If the file was deleted in A->B, the path as of C can be found
+ # by generating diff A->C ("base to base"), finding the diff file with
+ # `diff_file.old_path == position.old_path`, and taking `diff_file.new_path`.
+ # The path as of D can be found by taking diff C->D, finding the diff file
+ # with that same `old_path` and taking `diff_file.new_path`.
+ # The line number as of C can be found by using the LineMapper on diff A->C
+ # and providing the line number as of A.
+ # The line number as of D can be found by using the LineMapper on diff C->D
+ # and providing the line number as of C.
+
+ results = nil
+ results ||= trace_added_line(old_position) if old_position.added? || old_position.unchanged?
+ results ||= trace_removed_line(old_position) if old_position.removed? || old_position.unchanged?
+
+ return unless results
+
+ file_diff, old_line, new_line = results
+
+ Position.new(
+ old_path: file_diff.old_path,
+ new_path: file_diff.new_path,
+ head_sha: new_diff_refs.head_sha,
+ start_sha: new_diff_refs.start_sha,
+ base_sha: new_diff_refs.base_sha,
+ old_line: old_line,
+ new_line: new_line
+ )
+ end
+
+ private
+
+ def trace_added_line(old_position)
+ file_path = old_position.new_path
+
+ return unless diff_head_to_head
+
+ file_head_to_head = diff_head_to_head.find { |diff_file| diff_file.old_path == file_path }
+
+ file_path = file_head_to_head.new_path if file_head_to_head
+
+ new_line = LineMapper.new(file_head_to_head).old_to_new(old_position.new_line)
+
+ return unless new_line
+
+ file_diff = new_diffs.find { |diff_file| diff_file.new_path == file_path }
+ return unless file_diff
+
+ old_line = LineMapper.new(file_diff).new_to_old(new_line)
+
+ [file_diff, old_line, new_line]
+ end
+
+ def trace_removed_line(old_position)
+ file_path = old_position.old_path
+
+ return unless diff_base_to_base
+
+ file_base_to_base = diff_base_to_base.find { |diff_file| diff_file.old_path == file_path }
+
+ file_path = file_base_to_base.old_path if file_base_to_base
+
+ old_line = LineMapper.new(file_base_to_base).old_to_new(old_position.old_line)
+
+ return unless old_line
+
+ file_diff = new_diffs.find { |diff_file| diff_file.old_path == file_path }
+ return unless file_diff
+
+ new_line = LineMapper.new(file_diff).old_to_new(old_line)
+
+ [file_diff, old_line, new_line]
+ end
+
+ def diff_base_to_base
+ @diff_base_to_base ||= diff_files(old_diff_refs.base_sha || old_diff_refs.start_sha, new_diff_refs.base_sha || new_diff_refs.start_sha)
+ end
+
+ def diff_head_to_head
+ @diff_head_to_head ||= diff_files(old_diff_refs.head_sha, new_diff_refs.head_sha)
+ end
+
+ def new_diffs
+ @new_diffs ||= diff_files(new_diff_refs.start_sha, new_diff_refs.head_sha, use_base: true)
+ end
+
+ def diff_files(start_sha, head_sha, use_base: false)
+ base_sha = self.repository.merge_base(start_sha, head_sha) || start_sha
+
+ diffs = self.repository.raw_repository.diff(
+ use_base ? base_sha : start_sha,
+ head_sha,
+ {},
+ *paths
+ )
+
+ diffs.decorate! do |diff|
+ Gitlab::Diff::File.new(diff, repository: self.repository)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/email/message/repository_push.rb b/lib/gitlab/email/message/repository_push.rb
index 047c77c6fc2..97701b0cd42 100644
--- a/lib/gitlab/email/message/repository_push.rb
+++ b/lib/gitlab/email/message/repository_push.rb
@@ -33,11 +33,15 @@ module Gitlab
end
def commits
- @commits ||= (Commit.decorate(compare.commits, project) if compare)
+ return unless compare
+
+ @commits ||= Commit.decorate(compare.commits, project)
end
def diffs
- @diffs ||= (safe_diff_files(compare.diffs(max_files: 30), diff_refs) if compare)
+ return unless compare
+
+ @diffs ||= safe_diff_files(compare.diffs(max_files: 30), diff_refs: diff_refs, repository: project.repository)
end
def diffs_count
diff --git a/lib/gitlab/email/receiver.rb b/lib/gitlab/email/receiver.rb
index 97ef9851d71..1c671a7487b 100644
--- a/lib/gitlab/email/receiver.rb
+++ b/lib/gitlab/email/receiver.rb
@@ -104,15 +104,7 @@ module Gitlab
end
def create_note(reply)
- Notes::CreateService.new(
- sent_notification.project,
- sent_notification.recipient,
- note: reply,
- noteable_type: sent_notification.noteable_type,
- noteable_id: sent_notification.noteable_id,
- commit_id: sent_notification.commit_id,
- line_code: sent_notification.line_code
- ).execute
+ sent_notification.create_note(reply)
end
end
end
diff --git a/lib/gitlab/emoji.rb b/lib/gitlab/emoji.rb
new file mode 100644
index 00000000000..b63213ae208
--- /dev/null
+++ b/lib/gitlab/emoji.rb
@@ -0,0 +1,21 @@
+module Gitlab
+ module Emoji
+ extend self
+
+ def emojis
+ Gemojione.index.instance_variable_get(:@emoji_by_name)
+ end
+
+ def emojis_by_moji
+ Gemojione.index.instance_variable_get(:@emoji_by_moji)
+ end
+
+ def emojis_names
+ emojis.keys.sort
+ end
+
+ def emoji_filename(name)
+ emojis[name]["unicode"]
+ end
+ end
+end
diff --git a/lib/gitlab/git/hook.rb b/lib/gitlab/git/hook.rb
index 420c6883c45..9b681e636c7 100644
--- a/lib/gitlab/git/hook.rb
+++ b/lib/gitlab/git/hook.rb
@@ -1,6 +1,7 @@
module Gitlab
module Git
class Hook
+ GL_PROTOCOL = 'web'.freeze
attr_reader :name, :repo_path, :path
def initialize(name, repo_path)
@@ -14,7 +15,7 @@ module Gitlab
end
def trigger(gl_id, oldrev, newrev, ref)
- return true unless exists?
+ return [true, nil] unless exists?
case name
when "pre-receive", "post-receive"
@@ -34,7 +35,8 @@ module Gitlab
vars = {
'GL_ID' => gl_id,
- 'PWD' => repo_path
+ 'PWD' => repo_path,
+ 'GL_PROTOCOL' => GL_PROTOCOL
}
options = {
@@ -68,13 +70,10 @@ module Gitlab
end
def call_update_hook(gl_id, oldrev, newrev, ref)
- status = nil
-
Dir.chdir(repo_path) do
- status = system({ 'GL_ID' => gl_id }, path, ref, oldrev, newrev)
+ stdout, stderr, status = Open3.capture3({ 'GL_ID' => gl_id }, path, ref, oldrev, newrev)
+ [status.success?, stderr.presence || stdout]
end
-
- [status, nil]
end
def retrieve_error_message(stderr, stdout)
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index d2a0e316cbe..7679c7e4bb8 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -3,11 +3,12 @@ module Gitlab
DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive }
PUSH_COMMANDS = %w{ git-receive-pack }
- attr_reader :actor, :project
+ attr_reader :actor, :project, :protocol
- def initialize(actor, project)
+ def initialize(actor, project, protocol)
@actor = actor
@project = project
+ @protocol = protocol
end
def user
@@ -49,6 +50,8 @@ module Gitlab
end
def check(cmd, changes = nil)
+ return build_status_object(false, "Git access over #{protocol.upcase} is not allowed") unless protocol_allowed?
+
unless actor
return build_status_object(false, "No user or key was provided.")
end
@@ -164,6 +167,10 @@ module Gitlab
Gitlab::ForcePushCheck.force_push?(project, oldrev, newrev)
end
+ def protocol_allowed?
+ Gitlab::ProtocolAccess.allowed?(protocol)
+ end
+
private
def protected_branch_action(oldrev, newrev, branch_name)
diff --git a/lib/gitlab/github_import/branch_formatter.rb b/lib/gitlab/github_import/branch_formatter.rb
index a15fc84b418..7d2d545b84e 100644
--- a/lib/gitlab/github_import/branch_formatter.rb
+++ b/lib/gitlab/github_import/branch_formatter.rb
@@ -4,7 +4,7 @@ module Gitlab
delegate :repo, :sha, :ref, to: :raw_data
def exists?
- project.repository.branch_exists?(ref)
+ branch_exists? && commit_exists?
end
def name
@@ -15,11 +15,15 @@ module Gitlab
repo.present?
end
- def valid?
- repo.present?
+ private
+
+ def branch_exists?
+ project.repository.branch_exists?(ref)
end
- private
+ def commit_exists?
+ project.repository.commit(sha).present?
+ end
def short_id
sha.to_s[0..7]
diff --git a/lib/gitlab/github_import/importer.rb b/lib/gitlab/github_import/importer.rb
index 730978d502b..3932fcb1eda 100644
--- a/lib/gitlab/github_import/importer.rb
+++ b/lib/gitlab/github_import/importer.rb
@@ -131,8 +131,10 @@ module Gitlab
def clean_up_restored_branches(branches)
branches.each do |name, _|
client.delete_ref(repo, "heads/#{name}")
- project.repository.rm_branch(project.creator, name)
+ project.repository.delete_branch(name) rescue Rugged::ReferenceError
end
+
+ project.repository.after_remove_branch
end
def apply_labels(issuable)
diff --git a/lib/gitlab/github_import/pull_request_formatter.rb b/lib/gitlab/github_import/pull_request_formatter.rb
index 498b00cb658..a4ea2210abd 100644
--- a/lib/gitlab/github_import/pull_request_formatter.rb
+++ b/lib/gitlab/github_import/pull_request_formatter.rb
@@ -11,10 +11,10 @@ module Gitlab
description: description,
source_project: source_branch_project,
source_branch: source_branch_name,
- head_source_sha: source_branch_sha,
+ source_branch_sha: source_branch_sha,
target_project: target_branch_project,
target_branch: target_branch_name,
- base_target_sha: target_branch_sha,
+ target_branch_sha: target_branch_sha,
state: state,
milestone: milestone,
author_id: author_id,
diff --git a/lib/gitlab/graphs/commits.rb b/lib/gitlab/graphs/commits.rb
index 2122339d2db..3caf9036459 100644
--- a/lib/gitlab/graphs/commits.rb
+++ b/lib/gitlab/graphs/commits.rb
@@ -18,7 +18,7 @@ module Gitlab
end
def commit_per_day
- @commit_per_day ||= (@commits.size.to_f / @duration).round(1)
+ @commit_per_day ||= @commits.size / (@duration + 1)
end
def collect_data
diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb
index 78664f076eb..2249904145c 100644
--- a/lib/gitlab/import_export/command_line_util.rb
+++ b/lib/gitlab/import_export/command_line_util.rb
@@ -28,7 +28,8 @@ module Gitlab
end
def execute(cmd)
- _output, status = Gitlab::Popen.popen(cmd)
+ output, status = Gitlab::Popen.popen(cmd)
+ @shared.error(Gitlab::ImportExport::Error.new(output.to_s)) unless status.zero?
status.zero?
end
diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb
index 0ac6ff01e3b..025ecc12f9f 100644
--- a/lib/gitlab/import_export/project_tree_restorer.rb
+++ b/lib/gitlab/import_export/project_tree_restorer.rb
@@ -69,10 +69,19 @@ module Gitlab
# Example:
# +relation_key+ issues, loops through the list of *issues* and for each individual
# issue, finds any subrelations such as notes, creates them and assign them back to the hash
+ #
+ # Recursively calls this method if the sub-relation is a hash containing more sub-relations
def create_sub_relations(relation, tree_hash)
relation_key = relation.keys.first.to_s
+ return if tree_hash[relation_key].blank?
+
tree_hash[relation_key].each do |relation_item|
relation.values.flatten.each do |sub_relation|
+ # We just use author to get the user ID, do not attempt to create an instance.
+ next if sub_relation == :author
+
+ create_sub_relations(sub_relation, relation_item) if sub_relation.is_a?(Hash)
+
relation_hash, sub_relation = assign_relation_hash(relation_item, sub_relation)
relation_item[sub_relation.to_s] = create_relation(sub_relation, relation_hash) unless relation_hash.blank?
end
diff --git a/lib/gitlab/import_export/saver.rb b/lib/gitlab/import_export/saver.rb
index f38229c6c59..6a60b65071f 100644
--- a/lib/gitlab/import_export/saver.rb
+++ b/lib/gitlab/import_export/saver.rb
@@ -17,6 +17,7 @@ module Gitlab
Rails.logger.info("Saved project export #{archive_file}")
archive_file
else
+ @shared.error(Gitlab::ImportExport::Error.new("Unable to save #{archive_file} into #{@shared.export_path}"))
false
end
rescue => e
diff --git a/lib/gitlab/metrics/subscribers/rails_cache.rb b/lib/gitlab/metrics/subscribers/rails_cache.rb
index 8e345e8ae4a..aaed2184f44 100644
--- a/lib/gitlab/metrics/subscribers/rails_cache.rb
+++ b/lib/gitlab/metrics/subscribers/rails_cache.rb
@@ -2,11 +2,21 @@ module Gitlab
module Metrics
module Subscribers
# Class for tracking the total time spent in Rails cache calls
+ # http://guides.rubyonrails.org/active_support_instrumentation.html
class RailsCache < ActiveSupport::Subscriber
attach_to :active_support
def cache_read(event)
increment(:cache_read, event.duration)
+
+ return unless current_transaction
+ return if event.payload[:super_operation] == :fetch
+
+ if event.payload[:hit]
+ current_transaction.increment(:cache_read_hit_count, 1)
+ else
+ current_transaction.increment(:cache_read_miss_count, 1)
+ end
end
def cache_write(event)
@@ -21,6 +31,18 @@ module Gitlab
increment(:cache_exists, event.duration)
end
+ def cache_fetch_hit(event)
+ return unless current_transaction
+
+ current_transaction.increment(:cache_read_hit_count, 1)
+ end
+
+ def cache_generate(event)
+ return unless current_transaction
+
+ current_transaction.increment(:cache_read_miss_count, 1)
+ end
+
def increment(key, duration)
return unless current_transaction
diff --git a/lib/gitlab/protocol_access.rb b/lib/gitlab/protocol_access.rb
new file mode 100644
index 00000000000..21aefc884be
--- /dev/null
+++ b/lib/gitlab/protocol_access.rb
@@ -0,0 +1,13 @@
+module Gitlab
+ module ProtocolAccess
+ def self.allowed?(protocol)
+ if protocol == 'web'
+ true
+ elsif current_application_settings.enabled_git_access_protocol.blank?
+ true
+ else
+ protocol == current_application_settings.enabled_git_access_protocol
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/sidekiq_middleware/memory_killer.rb b/lib/gitlab/sidekiq_middleware/memory_killer.rb
index 4831c46c4be..104280f520a 100644
--- a/lib/gitlab/sidekiq_middleware/memory_killer.rb
+++ b/lib/gitlab/sidekiq_middleware/memory_killer.rb
@@ -29,11 +29,11 @@ module Gitlab
"in #{GRACE_TIME} seconds"
sleep(GRACE_TIME)
- Sidekiq.logger.warn "sending SIGTERM to PID #{Process.pid}"
+ Sidekiq.logger.warn "sending SIGTERM to PID #{Process.pid} - Worker #{worker.class} - JID-#{job['jid']}"
Process.kill('SIGTERM', Process.pid)
Sidekiq.logger.warn "waiting #{SHUTDOWN_WAIT} seconds before sending "\
- "#{SHUTDOWN_SIGNAL} to PID #{Process.pid}"
+ "#{SHUTDOWN_SIGNAL} to PID #{Process.pid} - Worker #{worker.class} - JID-#{job['jid']}"
sleep(SHUTDOWN_WAIT)
Sidekiq.logger.warn "sending #{SHUTDOWN_SIGNAL} to PID #{Process.pid} - Worker #{worker.class} - JID-#{job['jid']}"
diff --git a/lib/gitlab/timeless.rb b/lib/gitlab/timeless.rb
new file mode 100644
index 00000000000..b290c716f97
--- /dev/null
+++ b/lib/gitlab/timeless.rb
@@ -0,0 +1,16 @@
+module Gitlab
+ module Timeless
+ def self.timeless(model, &block)
+ original_record_timestamps = model.record_timestamps
+ model.record_timestamps = false
+
+ if block.arity.abs == 1
+ block.call(model)
+ else
+ block.call
+ end
+ ensure
+ model.record_timestamps = original_record_timestamps
+ end
+ end
+end
diff --git a/lib/gitlab/url_sanitizer.rb b/lib/gitlab/url_sanitizer.rb
index 7d02fe3c971..19dad699edf 100644
--- a/lib/gitlab/url_sanitizer.rb
+++ b/lib/gitlab/url_sanitizer.rb
@@ -4,10 +4,20 @@ module Gitlab
regexp = URI::Parser.new.make_regexp(['http', 'https', 'ssh', 'git'])
content.gsub(regexp) { |url| new(url).masked_url }
+ rescue Addressable::URI::InvalidURIError
+ content.gsub(regexp, '')
+ end
+
+ def self.valid?(url)
+ Addressable::URI.parse(url.strip)
+
+ true
+ rescue Addressable::URI::InvalidURIError
+ false
end
def initialize(url, credentials: nil)
- @url = Addressable::URI.parse(url)
+ @url = Addressable::URI.parse(url.strip)
@credentials = credentials
end
diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb
index ef1241f8600..6aeb49c0219 100644
--- a/lib/gitlab/workhorse.rb
+++ b/lib/gitlab/workhorse.rb
@@ -38,12 +38,10 @@ module Gitlab
end
def send_git_diff(repository, diff_refs)
- from, to = diff_refs
-
params = {
'RepoPath' => repository.path_to_repo,
- 'ShaFrom' => from.sha,
- 'ShaTo' => to.sha
+ 'ShaFrom' => diff_refs.start_sha,
+ 'ShaTo' => diff_refs.head_sha
}
[
@@ -52,11 +50,11 @@ module Gitlab
]
end
- def send_git_patch(repository, from, to)
+ def send_git_patch(repository, diff_refs)
params = {
'RepoPath' => repository.path_to_repo,
- 'ShaFrom' => from,
- 'ShaTo' => to
+ 'ShaFrom' => diff_refs.start_sha,
+ 'ShaTo' => diff_refs.head_sha
}
[
@@ -65,6 +63,18 @@ module Gitlab
]
end
+ def send_artifacts_entry(build, entry)
+ params = {
+ 'Archive' => build.artifacts_file.path,
+ 'Entry' => Base64.encode64(entry.path)
+ }
+
+ [
+ SEND_DATA_HEADER,
+ "artifacts-entry:#{encode(params)}"
+ ]
+ end
+
protected
def encode(hash)
diff --git a/lib/rouge/formatters/html_gitlab.rb b/lib/rouge/formatters/html_gitlab.rb
index 8c309efc7b8..3358ed6773e 100644
--- a/lib/rouge/formatters/html_gitlab.rb
+++ b/lib/rouge/formatters/html_gitlab.rb
@@ -143,18 +143,14 @@ module Rouge
'</span>'
end
end
- lines.join("\n")
- else
- if @linenos == 'inline'
- lines = lines.each_with_index.map do |line, index|
- number = index + @linenostart
- "<span class=\"linenos\">#{number}</span>#{line}"
- end
- lines.join("\n")
- else
- lines.join("\n")
+ elsif @linenos == 'inline'
+ lines = lines.each_with_index.map do |line, index|
+ number = index + @linenostart
+ "<span class=\"linenos\">#{number}</span>#{line}"
end
end
+
+ lines.join("\n")
end
def span(tok, val)
diff --git a/lib/tasks/gemojione.rake b/lib/tasks/gemojione.rake
index 030ee8bafcb..e930ace1041 100644
--- a/lib/tasks/gemojione.rake
+++ b/lib/tasks/gemojione.rake
@@ -13,7 +13,7 @@ namespace :gemojione do
aliases[real_name] << alias_name
end
- AwardEmoji.emojis.map do |name, emoji_hash|
+ Gitlab::AwardEmoji.emojis.map do |name, emoji_hash|
fpath = File.join(dir, "#{emoji_hash['unicode']}.png")
digest = Digest::SHA256.file(fpath).hexdigest
diff --git a/spec/controllers/admin/projects_controller_spec.rb b/spec/controllers/admin/projects_controller_spec.rb
index 4cb8b8da150..8eaacef2024 100644
--- a/spec/controllers/admin/projects_controller_spec.rb
+++ b/spec/controllers/admin/projects_controller_spec.rb
@@ -11,12 +11,12 @@ describe Admin::ProjectsController do
render_views
it 'retrieves the project for the given visibility level' do
- get :index, visibility_levels: [Gitlab::VisibilityLevel::PUBLIC]
+ get :index, visibility_level: [Gitlab::VisibilityLevel::PUBLIC]
expect(response.body).to match(project.name)
end
it 'does not retrieve the project' do
- get :index, visibility_levels: [Gitlab::VisibilityLevel::INTERNAL]
+ get :index, visibility_level: [Gitlab::VisibilityLevel::INTERNAL]
expect(response.body).not_to match(project.name)
end
end
diff --git a/spec/controllers/commit_controller_spec.rb b/spec/controllers/commit_controller_spec.rb
deleted file mode 100644
index a3a3309e15e..00000000000
--- a/spec/controllers/commit_controller_spec.rb
+++ /dev/null
@@ -1,246 +0,0 @@
-require 'spec_helper'
-
-describe Projects::CommitController do
- let(:project) { create(:project) }
- let(:user) { create(:user) }
- let(:commit) { project.commit("master") }
- let(:master_pickable_sha) { '7d3b0f7cff5f37573aea97cebfd5692ea1689924' }
- let(:master_pickable_commit) { project.commit(master_pickable_sha) }
-
- before do
- sign_in(user)
- project.team << [user, :master]
- end
-
- describe "#show" do
- shared_examples "export as" do |format|
- it "should generally work" do
- get(:show,
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- id: commit.id,
- format: format)
-
- expect(response).to be_success
- end
-
- it "should generate it" do
- expect_any_instance_of(Commit).to receive(:"to_#{format}")
-
- get(:show,
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- id: commit.id, format: format)
- end
-
- it "should render it" do
- get(:show,
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- id: commit.id, format: format)
-
- expect(response.body).to eq(commit.send(:"to_#{format}"))
- end
-
- it "should not escape Html" do
- allow_any_instance_of(Commit).to receive(:"to_#{format}").
- and_return('HTML entities &<>" ')
-
- get(:show,
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- id: commit.id, format: format)
-
- expect(response.body).not_to include('&amp;')
- expect(response.body).not_to include('&gt;')
- expect(response.body).not_to include('&lt;')
- expect(response.body).not_to include('&quot;')
- end
- end
-
- describe "as diff" do
- include_examples "export as", :diff
- let(:format) { :diff }
-
- it "should really only be a git diff" do
- get(:show,
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- id: commit.id,
- format: format)
-
- expect(response.body).to start_with("diff --git")
- end
-
- it "should really only be a git diff without whitespace changes" do
- get(:show,
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- id: '66eceea0db202bb39c4e445e8ca28689645366c5',
- # id: commit.id,
- format: format,
- w: 1)
-
- expect(response.body).to start_with("diff --git")
- # without whitespace option, there are more than 2 diff_splits
- diff_splits = assigns(:diffs).first.diff.split("\n")
- expect(diff_splits.length).to be <= 2
- end
- end
-
- describe "as patch" do
- include_examples "export as", :patch
- let(:format) { :patch }
-
- it "should really be a git email patch" do
- get(:show,
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- id: commit.id,
- format: format)
-
- expect(response.body).to start_with("From #{commit.id}")
- end
-
- it "should contain a git diff" do
- get(:show,
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- id: commit.id,
- format: format)
-
- expect(response.body).to match(/^diff --git/)
- end
- end
-
- context 'commit that removes a submodule' do
- render_views
-
- let(:fork_project) { create(:forked_project_with_submodules) }
- let(:commit) { fork_project.commit('remove-submodule') }
-
- before do
- fork_project.team << [user, :master]
- end
-
- it 'renders it' do
- get(:show,
- namespace_id: fork_project.namespace.to_param,
- project_id: fork_project.to_param,
- id: commit.id)
-
- expect(response).to be_success
- end
- end
- end
-
- describe "#branches" do
- it "contains branch and tags information" do
- get(:branches,
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- id: commit.id)
-
- expect(assigns(:branches)).to include("master", "feature_conflict")
- expect(assigns(:tags)).to include("v1.1.0")
- end
- end
-
- describe '#revert' do
- context 'when target branch is not provided' do
- it 'should render the 404 page' do
- post(:revert,
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- id: commit.id)
-
- expect(response).not_to be_success
- expect(response).to have_http_status(404)
- end
- end
-
- context 'when the revert was successful' do
- it 'should redirect to the commits page' do
- post(:revert,
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- target_branch: 'master',
- id: commit.id)
-
- expect(response).to redirect_to namespace_project_commits_path(project.namespace, project, 'master')
- expect(flash[:notice]).to eq('The commit has been successfully reverted.')
- end
- end
-
- context 'when the revert failed' do
- before do
- post(:revert,
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- target_branch: 'master',
- id: commit.id)
- end
-
- it 'should redirect to the commit page' do
- # Reverting a commit that has been already reverted.
- post(:revert,
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- target_branch: 'master',
- id: commit.id)
-
- expect(response).to redirect_to namespace_project_commit_path(project.namespace, project, commit.id)
- expect(flash[:alert]).to match('Sorry, we cannot revert this commit automatically.')
- end
- end
- end
-
- describe '#cherry_pick' do
- context 'when target branch is not provided' do
- it 'should render the 404 page' do
- post(:cherry_pick,
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- id: master_pickable_commit.id)
-
- expect(response).not_to be_success
- expect(response).to have_http_status(404)
- end
- end
-
- context 'when the cherry-pick was successful' do
- it 'should redirect to the commits page' do
- post(:cherry_pick,
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- target_branch: 'master',
- id: master_pickable_commit.id)
-
- expect(response).to redirect_to namespace_project_commits_path(project.namespace, project, 'master')
- expect(flash[:notice]).to eq('The commit has been successfully cherry-picked.')
- end
- end
-
- context 'when the cherry_pick failed' do
- before do
- post(:cherry_pick,
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- target_branch: 'master',
- id: master_pickable_commit.id)
- end
-
- it 'should redirect to the commit page' do
- # Cherry-picking a commit that has been already cherry-picked.
- post(:cherry_pick,
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- target_branch: 'master',
- id: master_pickable_commit.id)
-
- expect(response).to redirect_to namespace_project_commit_path(project.namespace, project, master_pickable_commit.id)
- expect(flash[:alert]).to match('Sorry, we cannot cherry-pick this commit automatically.')
- end
- end
- end
-end
diff --git a/spec/controllers/help_controller_spec.rb b/spec/controllers/help_controller_spec.rb
index 1f7fd517342..267d511c2db 100644
--- a/spec/controllers/help_controller_spec.rb
+++ b/spec/controllers/help_controller_spec.rb
@@ -11,7 +11,7 @@ describe HelpController do
context 'for Markdown formats' do
context 'when requested file exists' do
before do
- get :show, category: 'ssh', file: 'README', format: :md
+ get :show, path: 'ssh/README', format: :md
end
it 'assigns to @markdown' do
@@ -26,7 +26,7 @@ describe HelpController do
context 'when requested file is missing' do
it 'renders not found' do
- get :show, category: 'foo', file: 'bar', format: :md
+ get :show, path: 'foo/bar', format: :md
expect(response).to be_not_found
end
end
@@ -36,8 +36,7 @@ describe HelpController do
context 'when requested file exists' do
it 'renders the raw file' do
get :show,
- category: 'workflow/protected_branches',
- file: 'protected_branches1',
+ path: 'workflow/protected_branches/protected_branches1',
format: :png
expect(response).to be_success
expect(response.content_type).to eq 'image/png'
@@ -48,8 +47,7 @@ describe HelpController do
context 'when requested file is missing' do
it 'renders not found' do
get :show,
- category: 'foo',
- file: 'bar',
+ path: 'foo/bar',
format: :png
expect(response).to be_not_found
end
@@ -59,8 +57,7 @@ describe HelpController do
context 'for other formats' do
it 'always renders not found' do
get :show,
- category: 'ssh',
- file: 'README',
+ path: 'ssh/README',
format: :foo
expect(response).to be_not_found
end
diff --git a/spec/controllers/projects/commit_controller_spec.rb b/spec/controllers/projects/commit_controller_spec.rb
index 6e3db10e451..3001d32e719 100644
--- a/spec/controllers/projects/commit_controller_spec.rb
+++ b/spec/controllers/projects/commit_controller_spec.rb
@@ -1,9 +1,29 @@
-require 'rails_helper'
+require 'spec_helper'
describe Projects::CommitController do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:commit) { project.commit("master") }
+ let(:master_pickable_sha) { '7d3b0f7cff5f37573aea97cebfd5692ea1689924' }
+ let(:master_pickable_commit) { project.commit(master_pickable_sha) }
+
+ before do
+ sign_in(user)
+ project.team << [user, :master]
+ end
+
describe 'GET show' do
render_views
+ def go(extra_params = {})
+ params = {
+ namespace_id: project.namespace.to_param,
+ project_id: project.to_param
+ }
+
+ get :show, params.merge(extra_params)
+ end
+
let(:project) { create(:project) }
before do
@@ -15,7 +35,7 @@ describe Projects::CommitController do
context 'with valid id' do
it 'responds with 200' do
- go id: project.commit.id
+ go(id: commit.id)
expect(response).to be_ok
end
@@ -23,27 +43,274 @@ describe Projects::CommitController do
context 'with invalid id' do
it 'responds with 404' do
- go id: project.commit.id.reverse
+ go(id: commit.id.reverse)
expect(response).to be_not_found
end
end
it 'handles binary files' do
- get(:show,
+ go(id: TestEnv::BRANCH_SHA['binary-encoding'], format: 'html')
+
+ expect(response).to be_success
+ end
+
+ shared_examples "export as" do |format|
+ it "should generally work" do
+ go(id: commit.id, format: format)
+
+ expect(response).to be_success
+ end
+
+ it "should generate it" do
+ expect_any_instance_of(Commit).to receive(:"to_#{format}")
+
+ go(id: commit.id, format: format)
+ end
+
+ it "should render it" do
+ go(id: commit.id, format: format)
+
+ expect(response.body).to eq(commit.send(:"to_#{format}"))
+ end
+
+ it "should not escape Html" do
+ allow_any_instance_of(Commit).to receive(:"to_#{format}").
+ and_return('HTML entities &<>" ')
+
+ go(id: commit.id, format: format)
+
+ expect(response.body).not_to include('&amp;')
+ expect(response.body).not_to include('&gt;')
+ expect(response.body).not_to include('&lt;')
+ expect(response.body).not_to include('&quot;')
+ end
+ end
+
+ describe "as diff" do
+ include_examples "export as", :diff
+ let(:format) { :diff }
+
+ it "should really only be a git diff" do
+ go(id: commit.id, format: format)
+
+ expect(response.body).to start_with("diff --git")
+ end
+
+ it "should really only be a git diff without whitespace changes" do
+ go(id: '66eceea0db202bb39c4e445e8ca28689645366c5', format: format, w: 1)
+
+ expect(response.body).to start_with("diff --git")
+ # without whitespace option, there are more than 2 diff_splits
+ diff_splits = assigns(:diffs).first.diff.split("\n")
+ expect(diff_splits.length).to be <= 2
+ end
+ end
+
+ describe "as patch" do
+ include_examples "export as", :patch
+ let(:format) { :patch }
+
+ it "should really be a git email patch" do
+ go(id: commit.id, format: format)
+
+ expect(response.body).to start_with("From #{commit.id}")
+ end
+
+ it "should contain a git diff" do
+ go(id: commit.id, format: format)
+
+ expect(response.body).to match(/^diff --git/)
+ end
+ end
+
+ context 'commit that removes a submodule' do
+ render_views
+
+ let(:fork_project) { create(:forked_project_with_submodules, visibility_level: 20) }
+ let(:commit) { fork_project.commit('remove-submodule') }
+
+ it 'renders it' do
+ get(:show,
+ namespace_id: fork_project.namespace.to_param,
+ project_id: fork_project.to_param,
+ id: commit.id)
+
+ expect(response).to be_success
+ end
+ end
+ end
+
+ describe "GET branches" do
+ it "contains branch and tags information" do
+ get(:branches,
namespace_id: project.namespace.to_param,
project_id: project.to_param,
- id: TestEnv::BRANCH_SHA['binary-encoding'],
- format: "html")
+ id: commit.id)
- expect(response).to be_success
+ expect(assigns(:branches)).to include("master", "feature_conflict")
+ expect(assigns(:tags)).to include("v1.1.0")
+ end
+ end
+
+ describe 'POST revert' do
+ context 'when target branch is not provided' do
+ it 'should render the 404 page' do
+ post(:revert,
+ namespace_id: project.namespace.to_param,
+ project_id: project.to_param,
+ id: commit.id)
+
+ expect(response).not_to be_success
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'when the revert was successful' do
+ it 'should redirect to the commits page' do
+ post(:revert,
+ namespace_id: project.namespace.to_param,
+ project_id: project.to_param,
+ target_branch: 'master',
+ id: commit.id)
+
+ expect(response).to redirect_to namespace_project_commits_path(project.namespace, project, 'master')
+ expect(flash[:notice]).to eq('The commit has been successfully reverted.')
+ end
+ end
+
+ context 'when the revert failed' do
+ before do
+ post(:revert,
+ namespace_id: project.namespace.to_param,
+ project_id: project.to_param,
+ target_branch: 'master',
+ id: commit.id)
+ end
+
+ it 'should redirect to the commit page' do
+ # Reverting a commit that has been already reverted.
+ post(:revert,
+ namespace_id: project.namespace.to_param,
+ project_id: project.to_param,
+ target_branch: 'master',
+ id: commit.id)
+
+ expect(response).to redirect_to namespace_project_commit_path(project.namespace, project, commit.id)
+ expect(flash[:alert]).to match('Sorry, we cannot revert this commit automatically.')
+ end
+ end
+ end
+
+ describe 'POST cherry_pick' do
+ context 'when target branch is not provided' do
+ it 'should render the 404 page' do
+ post(:cherry_pick,
+ namespace_id: project.namespace.to_param,
+ project_id: project.to_param,
+ id: master_pickable_commit.id)
+
+ expect(response).not_to be_success
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'when the cherry-pick was successful' do
+ it 'should redirect to the commits page' do
+ post(:cherry_pick,
+ namespace_id: project.namespace.to_param,
+ project_id: project.to_param,
+ target_branch: 'master',
+ id: master_pickable_commit.id)
+
+ expect(response).to redirect_to namespace_project_commits_path(project.namespace, project, 'master')
+ expect(flash[:notice]).to eq('The commit has been successfully cherry-picked.')
+ end
end
- def go(id:)
- get :show,
+ context 'when the cherry_pick failed' do
+ before do
+ post(:cherry_pick,
+ namespace_id: project.namespace.to_param,
+ project_id: project.to_param,
+ target_branch: 'master',
+ id: master_pickable_commit.id)
+ end
+
+ it 'should redirect to the commit page' do
+ # Cherry-picking a commit that has been already cherry-picked.
+ post(:cherry_pick,
+ namespace_id: project.namespace.to_param,
+ project_id: project.to_param,
+ target_branch: 'master',
+ id: master_pickable_commit.id)
+
+ expect(response).to redirect_to namespace_project_commit_path(project.namespace, project, master_pickable_commit.id)
+ expect(flash[:alert]).to match('Sorry, we cannot cherry-pick this commit automatically.')
+ end
+ end
+ end
+
+ describe 'GET diff_for_path' do
+ def diff_for_path(extra_params = {})
+ params = {
namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- id: id
+ project_id: project.to_param
+ }
+
+ get :diff_for_path, params.merge(extra_params)
+ end
+
+ let(:existing_path) { '.gitmodules' }
+
+ context 'when the commit exists' do
+ context 'when the user has access to the project' do
+ context 'when the path exists in the diff' do
+ it 'enables diff notes' do
+ diff_for_path(id: commit.id, old_path: existing_path, new_path: existing_path)
+
+ expect(assigns(:diff_notes_disabled)).to be_falsey
+ expect(assigns(:comments_target)).to eq(noteable_type: 'Commit',
+ commit_id: commit.id)
+ end
+
+ it 'only renders the diffs for the path given' do
+ expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs, diff_refs, project|
+ expect(diffs.map(&:new_path)).to contain_exactly(existing_path)
+ meth.call(diffs, diff_refs, project)
+ end
+
+ diff_for_path(id: commit.id, old_path: existing_path, new_path: existing_path)
+ end
+ end
+
+ context 'when the path does not exist in the diff' do
+ before { diff_for_path(id: commit.id, old_path: existing_path.succ, new_path: existing_path.succ) }
+
+ it 'returns a 404' do
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+
+ context 'when the user does not have access to the project' do
+ before do
+ project.team.truncate
+ diff_for_path(id: commit.id, old_path: existing_path, new_path: existing_path)
+ end
+
+ it 'returns a 404' do
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+
+ context 'when the commit does not exist' do
+ before { diff_for_path(id: commit.id.succ, old_path: existing_path, new_path: existing_path) }
+
+ it 'returns a 404' do
+ expect(response).to have_http_status(404)
+ end
end
end
end
diff --git a/spec/controllers/projects/compare_controller_spec.rb b/spec/controllers/projects/compare_controller_spec.rb
index 4018dac95a2..4058d5e2453 100644
--- a/spec/controllers/projects/compare_controller_spec.rb
+++ b/spec/controllers/projects/compare_controller_spec.rb
@@ -64,4 +64,73 @@ describe Projects::CompareController do
expect(assigns(:commits)).to eq(nil)
end
end
+
+ describe 'GET diff_for_path' do
+ def diff_for_path(extra_params = {})
+ params = {
+ namespace_id: project.namespace.to_param,
+ project_id: project.to_param
+ }
+
+ get :diff_for_path, params.merge(extra_params)
+ end
+
+ let(:existing_path) { 'files/ruby/feature.rb' }
+
+ context 'when the from and to refs exist' do
+ context 'when the user has access to the project' do
+ context 'when the path exists in the diff' do
+ it 'disables diff notes' do
+ diff_for_path(from: ref_from, to: ref_to, old_path: existing_path, new_path: existing_path)
+
+ expect(assigns(:diff_notes_disabled)).to be_truthy
+ end
+
+ it 'only renders the diffs for the path given' do
+ expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs, diff_refs, project|
+ expect(diffs.map(&:new_path)).to contain_exactly(existing_path)
+ meth.call(diffs, diff_refs, project)
+ end
+
+ diff_for_path(from: ref_from, to: ref_to, old_path: existing_path, new_path: existing_path)
+ end
+ end
+
+ context 'when the path does not exist in the diff' do
+ before { diff_for_path(from: ref_from, to: ref_to, old_path: existing_path.succ, new_path: existing_path.succ) }
+
+ it 'returns a 404' do
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+
+ context 'when the user does not have access to the project' do
+ before do
+ project.team.truncate
+ diff_for_path(from: ref_from, to: ref_to, old_path: existing_path, new_path: existing_path)
+ end
+
+ it 'returns a 404' do
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+
+ context 'when the from ref does not exist' do
+ before { diff_for_path(from: ref_from.succ, to: ref_to, old_path: existing_path, new_path: existing_path) }
+
+ it 'returns a 404' do
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'when the to ref does not exist' do
+ before { diff_for_path(from: ref_from, to: ref_to.succ, old_path: existing_path, new_path: existing_path) }
+
+ it 'returns a 404' do
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
end
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index eff74e12869..210085e3b1a 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -10,7 +10,7 @@ describe Projects::MergeRequestsController do
project.team << [user, :master]
end
- describe '#new' do
+ describe 'GET new' do
context 'merge request that removes a submodule' do
render_views
@@ -34,7 +34,7 @@ describe Projects::MergeRequestsController do
end
end
- describe "#show" do
+ describe "GET show" do
shared_examples "export merge as" do |format|
it "should generally work" do
get(:show,
@@ -103,12 +103,12 @@ describe Projects::MergeRequestsController do
id: merge_request.iid,
format: :patch)
- expect(response.headers['Gitlab-Workhorse-Send-Data']).to start_with("git-format-patch:")
+ expect(response.headers[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("git-format-patch:")
end
end
end
- describe 'GET #index' do
+ describe 'GET index' do
def get_merge_requests
get :index,
namespace_id: project.namespace.to_param,
@@ -140,7 +140,7 @@ describe Projects::MergeRequestsController do
end
end
- describe 'PUT #update' do
+ describe 'PUT update' do
context 'there is no source project' do
let(:project) { create(:project) }
let(:fork_project) { create(:forked_project_with_submodules) }
@@ -168,7 +168,7 @@ describe Projects::MergeRequestsController do
end
end
- describe 'POST #merge' do
+ describe 'POST merge' do
let(:base_params) do
{
namespace_id: project.namespace.path,
@@ -212,7 +212,7 @@ describe Projects::MergeRequestsController do
context 'when the sha parameter matches the source SHA' do
def merge_with_sha
- post :merge, base_params.merge(sha: merge_request.source_sha)
+ post :merge, base_params.merge(sha: merge_request.diff_head_sha)
end
it 'returns :success' do
@@ -229,11 +229,11 @@ describe Projects::MergeRequestsController do
context 'when merge_when_build_succeeds is passed' do
def merge_when_build_succeeds
- post :merge, base_params.merge(sha: merge_request.source_sha, merge_when_build_succeeds: '1')
+ post :merge, base_params.merge(sha: merge_request.diff_head_sha, merge_when_build_succeeds: '1')
end
before do
- create(:ci_empty_pipeline, project: project, sha: merge_request.source_sha, ref: merge_request.source_branch)
+ create(:ci_empty_pipeline, project: project, sha: merge_request.diff_head_sha, ref: merge_request.source_branch)
end
it 'returns :merge_when_build_succeeds' do
@@ -266,7 +266,7 @@ describe Projects::MergeRequestsController do
end
end
- describe "DELETE #destroy" do
+ describe "DELETE destroy" do
it "denies access to users unless they're admin or project owner" do
delete :destroy, namespace_id: project.namespace.path, project_id: project.path, id: merge_request.iid
@@ -290,96 +290,210 @@ describe Projects::MergeRequestsController do
end
describe 'GET diffs' do
- def go(format: 'html')
- get :diffs,
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- id: merge_request.iid,
- format: format
+ def go(extra_params = {})
+ params = {
+ namespace_id: project.namespace.to_param,
+ project_id: project.to_param,
+ id: merge_request.iid
+ }
+
+ get :diffs, params.merge(extra_params)
end
- context 'as html' do
- it 'renders the diff template' do
- go
+ context 'with default params' do
+ context 'as html' do
+ before { go(format: 'html') }
- expect(response).to render_template('diffs')
+ it 'renders the diff template' do
+ expect(response).to render_template('diffs')
+ end
end
- end
- context 'as json' do
- it 'renders the diffs template to a string' do
- go format: 'json'
+ context 'as json' do
+ before { go(format: 'json') }
- expect(response).to render_template('projects/merge_requests/show/_diffs')
- expect(JSON.parse(response.body)).to have_key('html')
+ it 'renders the diffs template to a string' do
+ expect(response).to render_template('projects/merge_requests/show/_diffs')
+ expect(JSON.parse(response.body)).to have_key('html')
+ end
end
- end
-
- context 'with forked projects with submodules' do
- render_views
- let(:project) { create(:project) }
- let(:fork_project) { create(:forked_project_with_submodules) }
- let(:merge_request) { create(:merge_request_with_diffs, source_project: fork_project, source_branch: 'add-submodule-version-bump', target_branch: 'master', target_project: project) }
+ context 'with forked projects with submodules' do
+ render_views
- before do
- fork_project.build_forked_project_link(forked_to_project_id: fork_project.id, forked_from_project_id: project.id)
- fork_project.save
- merge_request.reload
- end
+ let(:project) { create(:project) }
+ let(:fork_project) { create(:forked_project_with_submodules) }
+ let(:merge_request) { create(:merge_request_with_diffs, source_project: fork_project, source_branch: 'add-submodule-version-bump', target_branch: 'master', target_project: project) }
- it 'renders' do
- go format: 'json'
+ before do
+ fork_project.build_forked_project_link(forked_to_project_id: fork_project.id, forked_from_project_id: project.id)
+ fork_project.save
+ merge_request.reload
+ go(format: 'json')
+ end
- expect(response).to be_success
- expect(response.body).to have_content('Subproject commit')
+ it 'renders' do
+ expect(response).to be_success
+ expect(response.body).to have_content('Subproject commit')
+ end
end
end
- end
- describe 'GET diffs with ignore_whitespace_change' do
- def go(format: 'html')
- get :diffs,
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- id: merge_request.iid,
- format: format,
- w: 1
- end
+ context 'with ignore_whitespace_change' do
+ context 'as html' do
+ before { go(format: 'html', w: 1) }
- context 'as html' do
- it 'renders the diff template' do
- go
+ it 'renders the diff template' do
+ expect(response).to render_template('diffs')
+ end
+ end
+
+ context 'as json' do
+ before { go(format: 'json', w: 1) }
- expect(response).to render_template('diffs')
+ it 'renders the diffs template to a string' do
+ expect(response).to render_template('projects/merge_requests/show/_diffs')
+ expect(JSON.parse(response.body)).to have_key('html')
+ end
end
end
- context 'as json' do
- it 'renders the diffs template to a string' do
- go format: 'json'
+ context 'with view' do
+ before { go(view: 'parallel') }
- expect(response).to render_template('projects/merge_requests/show/_diffs')
- expect(JSON.parse(response.body)).to have_key('html')
+ it 'saves the preferred diff view in a cookie' do
+ expect(response.cookies['diff_view']).to eq('parallel')
end
end
end
- describe 'GET diffs with view' do
- def go(extra_params = {})
+ describe 'GET diff_for_path' do
+ def diff_for_path(extra_params = {})
params = {
namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- id: merge_request.iid
+ project_id: project.to_param
}
- get :diffs, params.merge(extra_params)
+ get :diff_for_path, params.merge(extra_params)
end
- it 'saves the preferred diff view in a cookie' do
- go view: 'parallel'
+ context 'when an ID param is passed' do
+ let(:existing_path) { 'files/ruby/popen.rb' }
- expect(response.cookies['diff_view']).to eq('parallel')
+ context 'when the merge request exists' do
+ context 'when the user can view the merge request' do
+ context 'when the path exists in the diff' do
+ it 'enables diff notes' do
+ diff_for_path(id: merge_request.iid, old_path: existing_path, new_path: existing_path)
+
+ expect(assigns(:diff_notes_disabled)).to be_falsey
+ expect(assigns(:comments_target)).to eq(noteable_type: 'MergeRequest',
+ noteable_id: merge_request.id)
+ end
+
+ it 'only renders the diffs for the path given' do
+ expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs, diff_refs, project|
+ expect(diffs.map(&:new_path)).to contain_exactly(existing_path)
+ meth.call(diffs, diff_refs, project)
+ end
+
+ diff_for_path(id: merge_request.iid, old_path: existing_path, new_path: existing_path)
+ end
+ end
+
+ context 'when the path does not exist in the diff' do
+ before { diff_for_path(id: merge_request.iid, old_path: 'files/ruby/nopen.rb', new_path: 'files/ruby/nopen.rb') }
+
+ it 'returns a 404' do
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+
+ context 'when the user cannot view the merge request' do
+ before do
+ project.team.truncate
+ diff_for_path(id: merge_request.iid, old_path: existing_path, new_path: existing_path)
+ end
+
+ it 'returns a 404' do
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+
+ context 'when the merge request does not exist' do
+ before { diff_for_path(id: merge_request.iid.succ, old_path: existing_path, new_path: existing_path) }
+
+ it 'returns a 404' do
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'when the merge request belongs to a different project' do
+ let(:other_project) { create(:empty_project) }
+
+ before do
+ other_project.team << [user, :master]
+ diff_for_path(id: merge_request.iid, old_path: existing_path, new_path: existing_path, project_id: other_project.to_param)
+ end
+
+ it 'returns a 404' do
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+
+ context 'when source and target params are passed' do
+ let(:existing_path) { 'files/ruby/feature.rb' }
+
+ context 'when both branches are in the same project' do
+ it 'disables diff notes' do
+ diff_for_path(old_path: existing_path, new_path: existing_path, merge_request: { source_branch: 'feature', target_branch: 'master' })
+
+ expect(assigns(:diff_notes_disabled)).to be_truthy
+ end
+
+ it 'only renders the diffs for the path given' do
+ expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs, diff_refs, project|
+ expect(diffs.map(&:new_path)).to contain_exactly(existing_path)
+ meth.call(diffs, diff_refs, project)
+ end
+
+ diff_for_path(old_path: existing_path, new_path: existing_path, merge_request: { source_branch: 'feature', target_branch: 'master' })
+ end
+ end
+
+ context 'when the source branch is in a different project to the target' do
+ let(:other_project) { create(:project) }
+
+ before { other_project.team << [user, :master] }
+
+ context 'when the path exists in the diff' do
+ it 'disables diff notes' do
+ diff_for_path(old_path: existing_path, new_path: existing_path, merge_request: { source_project: other_project, source_branch: 'feature', target_branch: 'master' })
+
+ expect(assigns(:diff_notes_disabled)).to be_truthy
+ end
+
+ it 'only renders the diffs for the path given' do
+ expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs, diff_refs, project|
+ expect(diffs.map(&:new_path)).to contain_exactly(existing_path)
+ meth.call(diffs, diff_refs, project)
+ end
+
+ diff_for_path(old_path: existing_path, new_path: existing_path, merge_request: { source_project: other_project, source_branch: 'feature', target_branch: 'master' })
+ end
+ end
+
+ context 'when the path does not exist in the diff' do
+ before { diff_for_path(old_path: 'files/ruby/nopen.rb', new_path: 'files/ruby/nopen.rb', merge_request: { source_project: other_project, source_branch: 'feature', target_branch: 'master' }) }
+
+ it 'returns a 404' do
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
end
end
diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb
index 696cf276e57..83e38095feb 100644
--- a/spec/factories/notes.rb
+++ b/spec/factories/notes.rb
@@ -10,21 +10,46 @@ FactoryGirl.define do
on_issue
factory :note_on_commit, traits: [:on_commit]
- factory :note_on_commit_diff, traits: [:on_commit, :on_diff], class: LegacyDiffNote
factory :note_on_issue, traits: [:on_issue], aliases: [:votable_note]
factory :note_on_merge_request, traits: [:on_merge_request]
- factory :note_on_merge_request_diff, traits: [:on_merge_request, :on_diff], class: LegacyDiffNote
factory :note_on_project_snippet, traits: [:on_project_snippet]
factory :system_note, traits: [:system]
+ factory :legacy_diff_note_on_commit, traits: [:on_commit, :legacy_diff_note], class: LegacyDiffNote
+ factory :legacy_diff_note_on_merge_request, traits: [:on_merge_request, :legacy_diff_note], class: LegacyDiffNote
+
+ factory :diff_note_on_merge_request, traits: [:on_merge_request], class: DiffNote do
+ 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: noteable.diff_refs
+ )
+ end
+ end
+
+ factory :diff_note_on_commit, traits: [:on_commit], class: DiffNote do
+ 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: project.commit(commit_id).try(:diff_refs)
+ )
+ end
+ end
+
trait :on_commit do
noteable nil
- noteable_id nil
noteable_type 'Commit'
+ noteable_id nil
commit_id RepoHelpers.sample_commit.id
end
- trait :on_diff do
+ trait :legacy_diff_note do
line_code "0_184_184"
end
diff --git a/spec/factories/notification_settings.rb b/spec/factories/notification_settings.rb
new file mode 100644
index 00000000000..b5e96d18b8f
--- /dev/null
+++ b/spec/factories/notification_settings.rb
@@ -0,0 +1,8 @@
+FactoryGirl.define do
+ factory :notification_setting do
+ source factory: :empty_project
+ user
+ level 3
+ events []
+ end
+end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 5c8ddbebf0d..b682ced75ac 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -2,7 +2,7 @@ FactoryGirl.define do
# Project without repository
#
# Project does not have bare repository.
- # Use this factory if you dont need repository in tests
+ # Use this factory if you don't need repository in tests
factory :empty_project, class: 'Project' do
sequence(:name) { |n| "project#{n}" }
path { name.downcase.gsub(/\s/, '_') }
diff --git a/spec/features/admin/admin_abuse_reports_spec.rb b/spec/features/admin/admin_abuse_reports_spec.rb
new file mode 100644
index 00000000000..16baf7e9516
--- /dev/null
+++ b/spec/features/admin/admin_abuse_reports_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+describe "Admin::AbuseReports", feature: true, js: true do
+ let(:user) { create(:user) }
+
+ context 'as an admin' do
+ describe 'if a user has been reported for abuse' do
+ before do
+ create(:abuse_report, user: user)
+ login_as :admin
+ end
+
+ describe 'in the abuse report view' do
+ it "should present a link to the user's profile" do
+ visit admin_abuse_reports_path
+
+ expect(page).to have_link user.name, href: user_path(user)
+ end
+ end
+
+ describe 'in the profile page of the user' do
+ it 'should show a link to the admin view of the user' do
+ visit user_path(user)
+
+ expect(page).to have_link '', href: admin_user_path(user)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/admin/admin_disables_git_access_protocol_spec.rb b/spec/features/admin/admin_disables_git_access_protocol_spec.rb
new file mode 100644
index 00000000000..5b1c0460274
--- /dev/null
+++ b/spec/features/admin/admin_disables_git_access_protocol_spec.rb
@@ -0,0 +1,66 @@
+require 'rails_helper'
+
+feature 'Admin disables Git access protocol', feature: true do
+ let(:project) { create(:empty_project, :empty_repo) }
+ let(:admin) { create(:admin) }
+
+ background do
+ login_as(admin)
+ end
+
+ context 'with HTTP disabled' do
+ background do
+ disable_http_protocol
+ end
+
+ scenario 'shows only SSH url' do
+ visit_project
+
+ expect(page).to have_content("git clone #{project.ssh_url_to_repo}")
+ expect(page).not_to have_selector('#clone-dropdown')
+ end
+ end
+
+ context 'with SSH disabled' do
+ background do
+ disable_ssh_protocol
+ end
+
+ scenario 'shows only HTTP url' do
+ visit_project
+
+ expect(page).to have_content("git clone #{project.http_url_to_repo}")
+ expect(page).not_to have_selector('#clone-dropdown')
+ end
+ end
+
+ context 'with nothing disabled' do
+ background do
+ create(:personal_key, user: admin)
+ end
+
+ scenario 'shows default SSH url and protocol selection dropdown' do
+ visit_project
+
+ expect(page).to have_content("git clone #{project.ssh_url_to_repo}")
+ expect(page).to have_selector('#clone-dropdown')
+ end
+
+ end
+
+ def visit_project
+ visit namespace_project_path(project.namespace, project)
+ end
+
+ def disable_http_protocol
+ visit admin_application_settings_path
+ find('#application_setting_enabled_git_access_protocol').find(:xpath, 'option[2]').select_option
+ click_on 'Save'
+ end
+
+ def disable_ssh_protocol
+ visit admin_application_settings_path
+ find('#application_setting_enabled_git_access_protocol').find(:xpath, 'option[3]').select_option
+ click_on 'Save'
+ end
+end
diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb
index 1cb709c1de3..767504df251 100644
--- a/spec/features/admin/admin_users_spec.rb
+++ b/spec/features/admin/admin_users_spec.rb
@@ -144,9 +144,7 @@ describe "Admin::Users", feature: true do
before { click_link 'Impersonate' }
it 'logs in as the user when impersonate is clicked' do
- page.within '.sidebar-wrapper' do
- expect(page.find('.sidebar-user')['data-user']).to eql(another_user.username)
- end
+ expect(page.find(:css, '.header-user .profile-link')['data-user']).to eql(another_user.username)
end
it 'sees impersonation log out icon' do
@@ -158,9 +156,7 @@ describe "Admin::Users", feature: true do
it 'can log out of impersonated user back to original user' do
find(:css, 'li.impersonation a').click
- page.within '.sidebar-wrapper' do
- expect(page.find('.sidebar-user')['data-user']).to eql(@user.username)
- end
+ expect(page.find(:css, '.header-user .profile-link')['data-user']).to eql(@user.username)
end
it 'is redirected back to the impersonated users page in the admin after stopping' do
diff --git a/spec/features/expand_collapse_diffs_spec.rb b/spec/features/expand_collapse_diffs_spec.rb
new file mode 100644
index 00000000000..78bc888f2a6
--- /dev/null
+++ b/spec/features/expand_collapse_diffs_spec.rb
@@ -0,0 +1,207 @@
+require 'spec_helper'
+
+feature 'Expand and collapse diffs', js: true, feature: true do
+ include WaitForAjax
+
+ before do
+ login_as :admin
+ project = create(:project)
+ branch = 'expand-collapse-diffs'
+
+ # Ensure that undiffable.md is in .gitattributes
+ project.repository.copy_gitattributes(branch)
+ visit namespace_project_commit_path(project.namespace, project, project.commit(branch))
+ execute_script('window.ajaxUris = []; $(document).ajaxSend(function(event, xhr, settings) { ajaxUris.push(settings.url) });')
+ end
+
+ def file_container(filename)
+ find("[data-blob-diff-path*='#{filename}']")
+ end
+
+ # Use define_method instead of let (which is memoized) so that this just works across a
+ # reload.
+ #
+ files = [
+ 'small_diff.md', 'large_diff.md', 'large_diff_renamed.md', 'undiffable.md',
+ 'too_large.md', 'too_large_image.jpg'
+ ]
+
+ files.each do |file|
+ define_method(file.split('.').first) { file_container(file) }
+ end
+
+ context 'visiting a commit with collapsed diffs' do
+ it 'shows small diffs immediately' do
+ expect(small_diff).to have_selector('.code')
+ expect(small_diff).not_to have_selector('.nothing-here-block')
+ end
+
+ it 'collapses large diffs by default' do
+ expect(large_diff).not_to have_selector('.code')
+ expect(large_diff).to have_selector('.nothing-here-block')
+ end
+
+ it 'collapses large diffs for renamed files by default' do
+ expect(large_diff_renamed).not_to have_selector('.code')
+ expect(large_diff_renamed).to have_selector('.nothing-here-block')
+ expect(large_diff_renamed).to have_selector('.file-title .deletion')
+ expect(large_diff_renamed).to have_selector('.file-title .addition')
+ end
+
+ it 'shows non-renderable diffs as such immediately, regardless of their size' do
+ expect(undiffable).not_to have_selector('.code')
+ expect(undiffable).to have_selector('.nothing-here-block')
+ expect(undiffable).to have_content('gitattributes')
+ end
+
+ it 'does not allow diffs that are larger than the maximum size to be expanded' do
+ expect(too_large).not_to have_selector('.code')
+ expect(too_large).to have_selector('.nothing-here-block')
+ expect(too_large).to have_content('too large')
+ end
+
+ it 'shows image diffs immediately, regardless of their size' do
+ expect(too_large_image).not_to have_selector('.nothing-here-block')
+ expect(too_large_image).to have_selector('.image')
+ end
+
+ context 'expanding a diff for a renamed file' do
+ before do
+ large_diff_renamed.find('.nothing-here-block').click
+ wait_for_ajax
+ end
+
+ it 'shows the old content' do
+ old_line = large_diff_renamed.find('.line_content.old')
+
+ expect(old_line).to have_content('two copies')
+ end
+
+ it 'shows the new content' do
+ new_line = large_diff_renamed.find('.line_content.new', match: :prefer_exact)
+
+ expect(new_line).to have_content('three copies')
+ end
+ end
+
+ context 'expanding a large diff' do
+ before do
+ click_link('large_diff.md')
+ wait_for_ajax
+ end
+
+ it 'makes a request to get the content' do
+ ajax_uris = evaluate_script('ajaxUris')
+
+ expect(ajax_uris).not_to be_empty
+ expect(ajax_uris.first).to include('large_diff.md')
+ end
+
+ it 'shows the diff content' do
+ expect(large_diff).to have_selector('.code')
+ expect(large_diff).not_to have_selector('.nothing-here-block')
+ end
+
+ context 'adding a comment to the expanded diff' do
+ let(:comment_text) { 'A comment' }
+
+ before do
+ large_diff.find('.diff-line-num', match: :prefer_exact).hover
+ large_diff.find('.add-diff-note').click
+ large_diff.find('.note-textarea').send_keys comment_text
+ large_diff.find_button('Comment').click
+ wait_for_ajax
+ end
+
+ it 'adds the comment' do
+ expect(large_diff.find('.notes')).to have_content comment_text
+ end
+
+ context 'reloading the page' do
+ before { refresh }
+
+ it 'collapses the large diff by default' do
+ expect(large_diff).not_to have_selector('.code')
+ expect(large_diff).to have_selector('.nothing-here-block')
+ end
+
+ context 'expanding the diff' do
+ before do
+ click_link('large_diff.md')
+ wait_for_ajax
+ end
+
+ it 'shows the diff content' do
+ expect(large_diff).to have_selector('.code')
+ expect(large_diff).not_to have_selector('.nothing-here-block')
+ end
+
+ it 'shows the diff comment' do
+ expect(large_diff.find('.notes')).to have_content comment_text
+ end
+ end
+ end
+ end
+ end
+
+ context 'collapsing an expanded diff' do
+ before { click_link('small_diff.md') }
+
+ it 'hides the diff content' do
+ expect(small_diff).not_to have_selector('.code')
+ expect(small_diff).to have_selector('.nothing-here-block')
+ end
+
+ context 're-expanding the same diff' do
+ before { click_link('small_diff.md') }
+
+ it 'shows the diff content' do
+ expect(small_diff).to have_selector('.code')
+ expect(small_diff).not_to have_selector('.nothing-here-block')
+ end
+
+ it 'does not make a new HTTP request' do
+ expect(evaluate_script('ajaxUris')).not_to include(a_string_matching('small_diff.md'))
+ end
+ end
+ end
+ end
+
+ context 'expanding all diffs' do
+ before do
+ click_link('Expand all')
+ wait_for_ajax
+ execute_script('window.ajaxUris = []; $(document).ajaxSend(function(event, xhr, settings) { ajaxUris.push(settings.url) });')
+ end
+
+ it 'reloads the page with all diffs expanded' do
+ expect(small_diff).to have_selector('.code')
+ expect(small_diff).not_to have_selector('.nothing-here-block')
+
+ expect(large_diff).to have_selector('.code')
+ expect(large_diff).not_to have_selector('.nothing-here-block')
+ end
+
+ context 'collapsing an expanded diff' do
+ before { click_link('small_diff.md') }
+
+ it 'hides the diff content' do
+ expect(small_diff).not_to have_selector('.code')
+ expect(small_diff).to have_selector('.nothing-here-block')
+ end
+
+ context 're-expanding the same diff' do
+ before { click_link('small_diff.md') }
+
+ it 'shows the diff content' do
+ expect(small_diff).to have_selector('.code')
+ expect(small_diff).not_to have_selector('.nothing-here-block')
+ end
+
+ it 'does not make a new HTTP request' do
+ expect(evaluate_script('ajaxUris')).not_to include(a_string_matching('small_diff.md'))
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/groups/members/member_cannot_request_access_to_his_project_spec.rb b/spec/features/groups/members/member_cannot_request_access_to_his_project_spec.rb
new file mode 100644
index 00000000000..37c433cc09a
--- /dev/null
+++ b/spec/features/groups/members/member_cannot_request_access_to_his_project_spec.rb
@@ -0,0 +1,16 @@
+require 'spec_helper'
+
+feature 'Groups > Members > Member cannot request access to his project', feature: true do
+ let(:member) { create(:user) }
+ let(:group) { create(:group) }
+
+ background do
+ group.add_developer(member)
+ login_as(member)
+ visit group_path(group)
+ end
+
+ scenario 'member does not see the request access button' do
+ expect(page).not_to have_content 'Request Access'
+ end
+end
diff --git a/spec/features/help_pages_spec.rb b/spec/features/help_pages_spec.rb
index 8c6b669ce78..1e2306d7f59 100644
--- a/spec/features/help_pages_spec.rb
+++ b/spec/features/help_pages_spec.rb
@@ -6,7 +6,7 @@ describe 'Help Pages', feature: true do
login_as :user
end
it 'replace the variable $your_email with the email of the user' do
- visit help_page_path('ssh', 'README')
+ visit help_page_path('ssh/README')
expect(page).to have_content("ssh-keygen -t rsa -C \"#{@user.email}\"")
end
end
diff --git a/spec/features/issues/filter_issues_spec.rb b/spec/features/issues/filter_issues_spec.rb
index 006a06b8235..4b9b5394b61 100644
--- a/spec/features/issues/filter_issues_spec.rb
+++ b/spec/features/issues/filter_issues_spec.rb
@@ -7,6 +7,7 @@ describe 'Filter issues', feature: true do
let!(:user) { create(:user)}
let!(:milestone) { create(:milestone, project: project) }
let!(:label) { create(:label, project: project) }
+ let!(:issue1) { create(:issue, project: project) }
before do
project.team << [user, :master]
@@ -196,6 +197,7 @@ describe 'Filter issues', feature: true do
page.within '.labels-filter' do
click_link 'bug'
end
+ find('.dropdown-menu-close-icon').click
page.within '.issues-list' do
expect(page).to have_selector('.issue', count: 1)
@@ -287,7 +289,7 @@ describe 'Filter issues', feature: true do
wait_for_ajax
page.within '.issues-list' do
- expect(first('.issue')).to have_content('Frontend')
+ expect(page).to have_content('Frontend')
end
end
end
diff --git a/spec/features/merge_requests/created_from_fork_spec.rb b/spec/features/merge_requests/created_from_fork_spec.rb
index b4d2201c729..f676200ecf3 100644
--- a/spec/features/merge_requests/created_from_fork_spec.rb
+++ b/spec/features/merge_requests/created_from_fork_spec.rb
@@ -30,7 +30,7 @@ feature 'Merge request created from fork' do
given(:pipeline) do
create(:ci_pipeline_with_two_job, project: fork_project,
- sha: merge_request.last_commit.id,
+ sha: merge_request.diff_head_sha,
ref: merge_request.source_branch)
end
diff --git a/spec/features/merge_requests/diffs_spec.rb b/spec/features/merge_requests/diffs_spec.rb
new file mode 100644
index 00000000000..c9a0059645d
--- /dev/null
+++ b/spec/features/merge_requests/diffs_spec.rb
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+feature 'Diffs URL', js: true, feature: true do
+ before do
+ login_as :admin
+ @merge_request = create(:merge_request)
+ @project = @merge_request.source_project
+ end
+
+ context 'when visit with */* as accept header' do
+ before(:each) do
+ page.driver.add_header('Accept', '*/*')
+ end
+
+ it 'renders the notes' do
+ create :note_on_merge_request, project: @project, noteable: @merge_request, note: 'Rebasing with master'
+
+ visit diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)
+
+ # Load notes and diff through AJAX
+ expect(page).to have_css('.note-text', visible: false, text: 'Rebasing with master')
+ expect(page).to have_css('.diffs.tab-pane.active')
+ end
+ end
+end
diff --git a/spec/features/merge_requests/merge_when_build_succeeds_spec.rb b/spec/features/merge_requests/merge_when_build_succeeds_spec.rb
index c5e6412d7bf..96f7b8c9932 100644
--- a/spec/features/merge_requests/merge_when_build_succeeds_spec.rb
+++ b/spec/features/merge_requests/merge_when_build_succeeds_spec.rb
@@ -12,7 +12,7 @@ feature 'Merge When Build Succeeds', feature: true, js: true do
end
context "Active build for Merge Request" do
- let!(:pipeline) { create(:ci_pipeline, project: project, sha: merge_request.last_commit.id, ref: merge_request.source_branch) }
+ let!(:pipeline) { create(:ci_pipeline, project: project, sha: merge_request.diff_head_sha, ref: merge_request.source_branch) }
let!(:ci_build) { create(:ci_build, pipeline: pipeline) }
before do
@@ -47,7 +47,7 @@ feature 'Merge When Build Succeeds', feature: true, js: true do
merge_user: user, title: "MepMep", merge_when_build_succeeds: true)
end
- let!(:pipeline) { create(:ci_pipeline, project: project, sha: merge_request.last_commit.id, ref: merge_request.source_branch) }
+ let!(:pipeline) { create(:ci_pipeline, project: project, sha: merge_request.diff_head_sha, ref: merge_request.source_branch) }
let!(:ci_build) { create(:ci_build, pipeline: pipeline) }
before do
diff --git a/spec/features/merge_requests/only_allow_merge_if_build_succeeds.rb b/spec/features/merge_requests/only_allow_merge_if_build_succeeds.rb
index 65e9185ec24..80e8b8fc642 100644
--- a/spec/features/merge_requests/only_allow_merge_if_build_succeeds.rb
+++ b/spec/features/merge_requests/only_allow_merge_if_build_succeeds.rb
@@ -19,7 +19,7 @@ feature 'Only allow merge requests to be merged if the build succeeds', feature:
end
context 'when project has CI enabled' do
- let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: merge_request.last_commit.id, ref: merge_request.source_branch) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: merge_request.diff_head_sha, ref: merge_request.source_branch) }
context 'when merge requests can only be merged if the build succeeds' do
before do
diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb
index 737efcef45d..0b38c413f44 100644
--- a/spec/features/notes_on_merge_requests_spec.rb
+++ b/spec/features/notes_on_merge_requests_spec.rb
@@ -135,6 +135,28 @@ describe 'Comments', feature: true do
end
end
+ describe 'Handles cross-project system notes', js: true, feature: true do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :public) }
+ let(:project2) { create(:project, :private) }
+ let(:issue) { create(:issue, project: project2) }
+ let(:merge_request) { create(:merge_request, source_project: project, source_branch: 'markdown') }
+ let!(:note) { create(:note_on_merge_request, :system, noteable: merge_request, project: project, note: "mentioned in #{issue.to_reference(project)}") }
+
+ it 'shows the system note' do
+ login_as :admin
+ visit namespace_project_merge_request_path(project.namespace, project, merge_request)
+
+ expect(page).to have_css('.system-note')
+ end
+
+ it 'hides redacted system note' do
+ visit namespace_project_merge_request_path(project.namespace, project, merge_request)
+
+ expect(page).not_to have_css('.system-note')
+ end
+ end
+
describe 'On a merge request diff', js: true, feature: true do
let(:merge_request) { create(:merge_request) }
let(:project) { merge_request.source_project }
@@ -166,12 +188,14 @@ describe 'Comments', feature: true do
click_diff_line
is_expected.
- to have_css("tr[id='#{line_code}'] + .js-temp-notes-holder form",
+ to have_css("form[data-line-code='#{line_code}']",
count: 1)
end
it 'should be removed when canceled' do
- page.within(".diff-file form[id$='#{line_code}-true']") do
+ is_expected.to have_css('.js-temp-notes-holder')
+
+ page.within("form[data-line-code='#{line_code}']") do
find('.js-close-discussion-note-form').trigger('click')
end
@@ -229,6 +253,7 @@ describe 'Comments', feature: true do
end
def click_diff_line(data = line_code)
- execute_script("$('button[data-line-code=\"#{data}\"]').click()")
+ find(".line_holder[id='#{data}'] td.line_content").hover
+ find(".line_holder[id='#{data}'] button").trigger('click')
end
end
diff --git a/spec/features/pipelines_spec.rb b/spec/features/pipelines_spec.rb
index 98703ef3ac4..e7ee0aaea3c 100644
--- a/spec/features/pipelines_spec.rb
+++ b/spec/features/pipelines_spec.rb
@@ -123,7 +123,7 @@ describe "Pipelines" do
before { visit namespace_project_pipeline_path(project.namespace, project, pipeline) }
it 'showing a list of builds' do
- expect(page).to have_content('Tests')
+ expect(page).to have_content('Test')
expect(page).to have_content(@success.id)
expect(page).to have_content('Deploy')
expect(page).to have_content(@failed.id)
diff --git a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
index b8c06c383fb..fca40f68b01 100644
--- a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
+++ b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
@@ -19,12 +19,12 @@ feature 'User wants to add a .gitlab-ci.yml file', feature: true do
find('.js-gitlab-ci-yml-selector').click
wait_for_ajax
within '.gitlab-ci-yml-selector' do
- find('.dropdown-input-field').set('jekyll')
- find('.dropdown-content li', text: 'jekyll').click
+ find('.dropdown-input-field').set('Jekyll')
+ find('.dropdown-content li', text: 'Jekyll').click
end
wait_for_ajax
- expect(page).to have_css('.gitlab-ci-yml-selector .dropdown-toggle-text', text: 'jekyll')
+ expect(page).to have_css('.gitlab-ci-yml-selector .dropdown-toggle-text', text: 'Jekyll')
expect(page).to have_content('This file is a template, and might need editing before it works on your project')
expect(page).to have_content('jekyll build -d test')
end
diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb
index 9d66f76ef58..bc3bf53fe9d 100644
--- a/spec/features/projects/import_export/import_file_spec.rb
+++ b/spec/features/projects/import_export/import_file_spec.rb
@@ -42,6 +42,23 @@ feature 'project import', feature: true, js: true do
expect(project.import_status).to eq('finished')
end
+ scenario 'invalid project' do
+ project = create(:project, namespace_id: 2)
+
+ visit new_project_path
+
+ select2('2', from: '#project_namespace_id')
+ fill_in :project_path, with: project.name, visible: true
+ click_link 'GitLab export'
+
+ attach_file('file', file)
+ click_on 'Import project'
+
+ page.within('.flash-container') do
+ expect(page).to have_content('Project could not be imported')
+ end
+ end
+
def wiki_exists?
wiki = ProjectWiki.new(project)
File.exist?(wiki.repository.path_to_repo) && !wiki.repository.empty?
diff --git a/spec/features/projects/labels/update_prioritization_spec.rb b/spec/features/projects/labels/update_prioritization_spec.rb
index 6a39c302f55..98ba93b4036 100644
--- a/spec/features/projects/labels/update_prioritization_spec.rb
+++ b/spec/features/projects/labels/update_prioritization_spec.rb
@@ -76,7 +76,7 @@ feature 'Prioritize labels', feature: true do
expect(page.all('li').last).to have_content('bug')
end
- visit current_url
+ refresh
wait_for_ajax
page.within('.prioritized-labels') do
diff --git a/spec/features/projects/members/group_member_cannot_request_access_to_his_group_project_spec.rb b/spec/features/projects/members/group_member_cannot_request_access_to_his_group_project_spec.rb
index 4d5d656f00c..ff9b6007806 100644
--- a/spec/features/projects/members/group_member_cannot_request_access_to_his_group_project_spec.rb
+++ b/spec/features/projects/members/group_member_cannot_request_access_to_his_group_project_spec.rb
@@ -5,9 +5,6 @@ feature 'Projects > Members > Group member cannot request access to his group pr
let(:group) { create(:group) }
let(:project) { create(:project, namespace: group) }
- background do
- end
-
scenario 'owner does not see the request access button' do
group.add_owner(user)
login_and_visit_project_page(user)
diff --git a/spec/features/projects/members/member_cannot_request_access_to_his_project_spec.rb b/spec/features/projects/members/member_cannot_request_access_to_his_project_spec.rb
new file mode 100644
index 00000000000..9564347e733
--- /dev/null
+++ b/spec/features/projects/members/member_cannot_request_access_to_his_project_spec.rb
@@ -0,0 +1,16 @@
+require 'spec_helper'
+
+feature 'Projects > Members > Member cannot request access to his project', feature: true do
+ let(:member) { create(:user) }
+ let(:project) { create(:project) }
+
+ background do
+ project.team << [member, :developer]
+ login_as(member)
+ visit namespace_project_path(project.namespace, project)
+ end
+
+ scenario 'member does not see the request access button' do
+ expect(page).not_to have_content 'Request Access'
+ end
+end
diff --git a/spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb b/spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb
new file mode 100644
index 00000000000..0e54c4fdf20
--- /dev/null
+++ b/spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb
@@ -0,0 +1,16 @@
+require 'spec_helper'
+
+feature 'Projects > Members > Owner cannot request access to his project', feature: true do
+ let(:owner) { create(:user) }
+ let(:project) { create(:project) }
+
+ background do
+ project.team << [owner, :owner]
+ login_as(owner)
+ visit namespace_project_path(project.namespace, project)
+ end
+
+ scenario 'owner does not see the request access button' do
+ expect(page).not_to have_content 'Request Access'
+ end
+end
diff --git a/spec/features/protected_branches_spec.rb b/spec/features/protected_branches_spec.rb
new file mode 100644
index 00000000000..d94dee0c797
--- /dev/null
+++ b/spec/features/protected_branches_spec.rb
@@ -0,0 +1,84 @@
+require 'spec_helper'
+
+feature 'Projected Branches', feature: true, js: true do
+ let(:user) { create(:user, :admin) }
+ let(:project) { create(:project) }
+
+ before { login_as(user) }
+
+ def set_protected_branch_name(branch_name)
+ find(".js-protected-branch-select").click
+ find(".dropdown-input-field").set(branch_name)
+ click_on "Create Protected Branch: #{branch_name}"
+ end
+
+ describe "explicit protected branches" do
+ it "allows creating explicit protected branches" do
+ visit namespace_project_protected_branches_path(project.namespace, project)
+ set_protected_branch_name('some-branch')
+ click_on "Protect"
+
+ within(".protected-branches-list") { expect(page).to have_content('some-branch') }
+ expect(ProtectedBranch.count).to eq(1)
+ expect(ProtectedBranch.last.name).to eq('some-branch')
+ end
+
+ it "displays the last commit on the matching branch if it exists" do
+ commit = create(:commit, project: project)
+ project.repository.add_branch(user, 'some-branch', commit.id)
+
+ visit namespace_project_protected_branches_path(project.namespace, project)
+ set_protected_branch_name('some-branch')
+ click_on "Protect"
+
+ within(".protected-branches-list") { expect(page).to have_content(commit.id[0..7]) }
+ end
+
+ it "displays an error message if the named branch does not exist" do
+ visit namespace_project_protected_branches_path(project.namespace, project)
+ set_protected_branch_name('some-branch')
+ click_on "Protect"
+
+ within(".protected-branches-list") { expect(page).to have_content('branch was removed') }
+ end
+ end
+
+ describe "wildcard protected branches" do
+ it "allows creating protected branches with a wildcard" do
+ visit namespace_project_protected_branches_path(project.namespace, project)
+ set_protected_branch_name('*-stable')
+ click_on "Protect"
+
+ within(".protected-branches-list") { expect(page).to have_content('*-stable') }
+ expect(ProtectedBranch.count).to eq(1)
+ expect(ProtectedBranch.last.name).to eq('*-stable')
+ end
+
+ it "displays the number of matching branches" do
+ project.repository.add_branch(user, 'production-stable', 'master')
+ project.repository.add_branch(user, 'staging-stable', 'master')
+
+ visit namespace_project_protected_branches_path(project.namespace, project)
+ set_protected_branch_name('*-stable')
+ click_on "Protect"
+
+ within(".protected-branches-list") { expect(page).to have_content("2 matching branches") }
+ end
+
+ it "displays all the branches matching the wildcard" do
+ project.repository.add_branch(user, 'production-stable', 'master')
+ project.repository.add_branch(user, 'staging-stable', 'master')
+ project.repository.add_branch(user, 'development', 'master')
+ create(:protected_branch, project: project, name: "*-stable")
+
+ visit namespace_project_protected_branches_path(project.namespace, project)
+ click_on "2 matching branches"
+
+ within(".protected-branches-list") do
+ expect(page).to have_content("production-stable")
+ expect(page).to have_content("staging-stable")
+ expect(page).not_to have_content("development")
+ end
+ end
+ end
+end
diff --git a/spec/features/search_spec.rb b/spec/features/search_spec.rb
index 85923f0a19d..d0a301038c4 100644
--- a/spec/features/search_spec.rb
+++ b/spec/features/search_spec.rb
@@ -3,6 +3,8 @@ require 'spec_helper'
describe "Search", feature: true do
let(:user) { create(:user) }
let(:project) { create(:project, namespace: user.namespace) }
+ let!(:issue) { create(:issue, project: project, assignee: user) }
+ let!(:issue2) { create(:issue, project: project, author: user) }
before do
login_with(user)
diff --git a/spec/fixtures/blockquote_fence_after.md b/spec/fixtures/blockquote_fence_after.md
new file mode 100644
index 00000000000..2652a842c0e
--- /dev/null
+++ b/spec/fixtures/blockquote_fence_after.md
@@ -0,0 +1,115 @@
+Single `>>>` inside code block:
+
+```
+# Code
+>>>
+# Code
+```
+
+Double `>>>` inside code block:
+
+```txt
+# Code
+>>>
+# Code
+>>>
+# Code
+```
+
+Blockquote outside code block:
+
+> Quote
+
+Code block inside blockquote:
+
+> Quote
+>
+> ```
+> # Code
+> ```
+>
+> Quote
+
+Single `>>>` inside code block inside blockquote:
+
+> Quote
+>
+> ```
+> # Code
+> >>>
+> # Code
+> ```
+>
+> Quote
+
+Double `>>>` inside code block inside blockquote:
+
+> Quote
+>
+> ```
+> # Code
+> >>>
+> # Code
+> >>>
+> # Code
+> ```
+>
+> Quote
+
+Single `>>>` inside HTML:
+
+<pre>
+# Code
+>>>
+# Code
+</pre>
+
+Double `>>>` inside HTML:
+
+<pre>
+# Code
+>>>
+# Code
+>>>
+# Code
+</pre>
+
+Blockquote outside HTML:
+
+> Quote
+
+HTML inside blockquote:
+
+> Quote
+>
+> <pre>
+> # Code
+> </pre>
+>
+> Quote
+
+Single `>>>` inside HTML inside blockquote:
+
+> Quote
+>
+> <pre>
+> # Code
+> >>>
+> # Code
+> </pre>
+>
+> Quote
+
+Double `>>>` inside HTML inside blockquote:
+
+> Quote
+>
+> <pre>
+> # Code
+> >>>
+> # Code
+> >>>
+> # Code
+> </pre>
+>
+> Quote
diff --git a/spec/fixtures/blockquote_fence_before.md b/spec/fixtures/blockquote_fence_before.md
new file mode 100644
index 00000000000..d52eec72896
--- /dev/null
+++ b/spec/fixtures/blockquote_fence_before.md
@@ -0,0 +1,131 @@
+Single `>>>` inside code block:
+
+```
+# Code
+>>>
+# Code
+```
+
+Double `>>>` inside code block:
+
+```txt
+# Code
+>>>
+# Code
+>>>
+# Code
+```
+
+Blockquote outside code block:
+
+>>>
+Quote
+>>>
+
+Code block inside blockquote:
+
+>>>
+Quote
+
+```
+# Code
+```
+
+Quote
+>>>
+
+Single `>>>` inside code block inside blockquote:
+
+>>>
+Quote
+
+```
+# Code
+>>>
+# Code
+```
+
+Quote
+>>>
+
+Double `>>>` inside code block inside blockquote:
+
+>>>
+Quote
+
+```
+# Code
+>>>
+# Code
+>>>
+# Code
+```
+
+Quote
+>>>
+
+Single `>>>` inside HTML:
+
+<pre>
+# Code
+>>>
+# Code
+</pre>
+
+Double `>>>` inside HTML:
+
+<pre>
+# Code
+>>>
+# Code
+>>>
+# Code
+</pre>
+
+Blockquote outside HTML:
+
+>>>
+Quote
+>>>
+
+HTML inside blockquote:
+
+>>>
+Quote
+
+<pre>
+# Code
+</pre>
+
+Quote
+>>>
+
+Single `>>>` inside HTML inside blockquote:
+
+>>>
+Quote
+
+<pre>
+# Code
+>>>
+# Code
+</pre>
+
+Quote
+>>>
+
+Double `>>>` inside HTML inside blockquote:
+
+>>>
+Quote
+
+<pre>
+# Code
+>>>
+# Code
+>>>
+# Code
+</pre>
+
+Quote
+>>>
diff --git a/spec/fixtures/parallel_diff_result.yml b/spec/fixtures/parallel_diff_result.yml
index a8b7907d4ba..7d01183e3ef 100644
--- a/spec/fixtures/parallel_diff_result.yml
+++ b/spec/fixtures/parallel_diff_result.yml
@@ -3,322 +3,818 @@
:type: match
:number: 6
:text: "@@ -6,12 +6,18 @@ module Popen"
- :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6
+ :line_code:
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line:
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type: match
:number: 6
:text: "@@ -6,12 +6,18 @@ module Popen"
- :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6
+ :line_code:
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line:
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number: 6
:text: |2
<span id="LC6" class="line"></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 6
+ :new_line: 6
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type:
:number: 6
:text: |2
<span id="LC6" class="line"></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 6
+ :new_line: 6
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number: 7
:text: |2
<span id="LC7" class="line"> <span class="k">def</span> <span class="nf">popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="kp">nil</span><span class="p">)</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 7
+ :new_line: 7
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type:
:number: 7
:text: |2
<span id="LC7" class="line"> <span class="k">def</span> <span class="nf">popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="kp">nil</span><span class="p">)</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 7
+ :new_line: 7
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number: 8
:text: |2
<span id="LC8" class="line"> <span class="k">unless</span> <span class="n">cmd</span><span class="p">.</span><span class="nf">is_a?</span><span class="p">(</span><span class="no">Array</span><span class="p">)</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 8
+ :new_line: 8
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type:
:number: 8
:text: |2
<span id="LC8" class="line"> <span class="k">unless</span> <span class="n">cmd</span><span class="p">.</span><span class="nf">is_a?</span><span class="p">(</span><span class="no">Array</span><span class="p">)</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 8
+ :new_line: 8
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type: old
:number: 9
:text: |
-<span id="LC9" class="line"> <span class="k">raise</span> <span class="s2">&quot;System commands must be given as an array of strings&quot;</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 9
+ :new_line:
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type: new
:number: 9
:text: |
+<span id="LC9" class="line"> <span class="k">raise</span> <span class="no"><span class='idiff left'>RuntimeError</span></span><span class="p"><span class='idiff'>,</span></span><span class='idiff right'> </span><span class="s2">&quot;System commands must be given as an array of strings&quot;</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line: 9
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number: 10
:text: |2
<span id="LC10" class="line"> <span class="k">end</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 10
+ :new_line: 10
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type:
:number: 10
:text: |2
<span id="LC10" class="line"> <span class="k">end</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 10
+ :new_line: 10
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number: 11
:text: |2
<span id="LC11" class="line"></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_11_11
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 11
+ :new_line: 11
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type:
:number: 11
:text: |2
<span id="LC11" class="line"></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_11_11
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 11
+ :new_line: 11
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number: 12
:text: |2
<span id="LC12" class="line"> <span class="n">path</span> <span class="o">||=</span> <span class="no">Dir</span><span class="p">.</span><span class="nf">pwd</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_12_12
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 12
+ :new_line: 12
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type:
:number: 12
:text: |2
<span id="LC12" class="line"> <span class="n">path</span> <span class="o">||=</span> <span class="no">Dir</span><span class="p">.</span><span class="nf">pwd</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_12_12
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 12
+ :new_line: 12
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type: old
:number: 13
:text: |
-<span id="LC13" class="line"> <span class="n">vars</span> <span class="o">=</span> <span class="p">{</span> <span class="s2">&quot;PWD&quot;</span> <span class="o">=&gt;</span> <span class="n">path</span> <span class="p">}</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_13_13
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 13
+ :new_line:
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type: old
:number:
:text: ''
:line_code:
+ :position:
- :left:
:type: old
:number: 14
:text: |
-<span id="LC14" class="line"> <span class="n">options</span> <span class="o">=</span> <span class="p">{</span> <span class="ss">chdir: </span><span class="n">path</span> <span class="p">}</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_14_13
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 14
+ :new_line:
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type: new
:number: 13
:text: |
+<span id="LC13" class="line"></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_13
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line: 13
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number:
:text: ''
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_14
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line: 14
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type: new
:number: 14
:text: |
+<span id="LC14" class="line"> <span class="n">vars</span> <span class="o">=</span> <span class="p">{</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_14
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line: 14
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number:
:text: ''
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_15
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line: 15
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type: new
:number: 15
:text: |
+<span id="LC15" class="line"> <span class="s2">&quot;PWD&quot;</span> <span class="o">=&gt;</span> <span class="n">path</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_15
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line: 15
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number:
:text: ''
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_16
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line: 16
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type: new
:number: 16
:text: |
+<span id="LC16" class="line"> <span class="p">}</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_16
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line: 16
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number:
:text: ''
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_17
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line: 17
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type: new
:number: 17
:text: |
+<span id="LC17" class="line"></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_17
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line: 17
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number:
:text: ''
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_18
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line: 18
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type: new
:number: 18
:text: |
+<span id="LC18" class="line"> <span class="n">options</span> <span class="o">=</span> <span class="p">{</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_18
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line: 18
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number:
:text: ''
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_19
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line: 19
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type: new
:number: 19
:text: |
+<span id="LC19" class="line"> <span class="ss">chdir: </span><span class="n">path</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_19
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line: 19
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number:
:text: ''
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_20
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line: 20
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type: new
:number: 20
:text: |
+<span id="LC20" class="line"> <span class="p">}</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_20
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line: 20
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number: 15
:text: |2
<span id="LC21" class="line"></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_21
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 15
+ :new_line: 21
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type:
:number: 21
:text: |2
<span id="LC21" class="line"></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_21
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 15
+ :new_line: 21
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number: 16
:text: |2
<span id="LC22" class="line"> <span class="k">unless</span> <span class="no">File</span><span class="p">.</span><span class="nf">directory?</span><span class="p">(</span><span class="n">path</span><span class="p">)</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_16_22
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 16
+ :new_line: 22
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type:
:number: 22
:text: |2
<span id="LC22" class="line"> <span class="k">unless</span> <span class="no">File</span><span class="p">.</span><span class="nf">directory?</span><span class="p">(</span><span class="n">path</span><span class="p">)</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_16_22
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 16
+ :new_line: 22
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number: 17
:text: |2
<span id="LC23" class="line"> <span class="no">FileUtils</span><span class="p">.</span><span class="nf">mkdir_p</span><span class="p">(</span><span class="n">path</span><span class="p">)</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_17_23
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 17
+ :new_line: 23
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type:
:number: 23
:text: |2
<span id="LC23" class="line"> <span class="no">FileUtils</span><span class="p">.</span><span class="nf">mkdir_p</span><span class="p">(</span><span class="n">path</span><span class="p">)</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_17_23
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 17
+ :new_line: 23
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type: match
:number: 19
:text: "@@ -19,6 +25,7 @@ module Popen"
- :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25
+ :line_code:
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line:
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type: match
:number: 25
:text: "@@ -19,6 +25,7 @@ module Popen"
- :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25
+ :line_code:
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line:
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number: 19
:text: |2
<span id="LC25" class="line"></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 19
+ :new_line: 25
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type:
:number: 25
:text: |2
<span id="LC25" class="line"></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 19
+ :new_line: 25
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number: 20
:text: |2
<span id="LC26" class="line"> <span class="vi">@cmd_output</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_20_26
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 20
+ :new_line: 26
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type:
:number: 26
:text: |2
<span id="LC26" class="line"> <span class="vi">@cmd_output</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_20_26
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 20
+ :new_line: 26
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number: 21
:text: |2
<span id="LC27" class="line"> <span class="vi">@cmd_status</span> <span class="o">=</span> <span class="mi">0</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_21_27
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 21
+ :new_line: 27
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type:
:number: 27
:text: |2
<span id="LC27" class="line"> <span class="vi">@cmd_status</span> <span class="o">=</span> <span class="mi">0</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_21_27
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 21
+ :new_line: 27
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number:
:text: ''
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_28
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line: 28
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type: new
:number: 28
:text: |
+<span id="LC28" class="line"></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_28
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line:
+ :new_line: 28
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number: 22
:text: |2
<span id="LC29" class="line"> <span class="no">Open3</span><span class="p">.</span><span class="nf">popen3</span><span class="p">(</span><span class="n">vars</span><span class="p">,</span> <span class="o">*</span><span class="n">cmd</span><span class="p">,</span> <span class="n">options</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">stdin</span><span class="p">,</span> <span class="n">stdout</span><span class="p">,</span> <span class="n">stderr</span><span class="p">,</span> <span class="n">wait_thr</span><span class="o">|</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_29
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 22
+ :new_line: 29
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type:
:number: 29
:text: |2
<span id="LC29" class="line"> <span class="no">Open3</span><span class="p">.</span><span class="nf">popen3</span><span class="p">(</span><span class="n">vars</span><span class="p">,</span> <span class="o">*</span><span class="n">cmd</span><span class="p">,</span> <span class="n">options</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">stdin</span><span class="p">,</span> <span class="n">stdout</span><span class="p">,</span> <span class="n">stderr</span><span class="p">,</span> <span class="n">wait_thr</span><span class="o">|</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_29
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 22
+ :new_line: 29
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number: 23
:text: |2
<span id="LC30" class="line"> <span class="vi">@cmd_output</span> <span class="o">&lt;&lt;</span> <span class="n">stdout</span><span class="p">.</span><span class="nf">read</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_23_30
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 23
+ :new_line: 30
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type:
:number: 30
:text: |2
<span id="LC30" class="line"> <span class="vi">@cmd_output</span> <span class="o">&lt;&lt;</span> <span class="n">stdout</span><span class="p">.</span><span class="nf">read</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_23_30
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 23
+ :new_line: 30
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
- :left:
:type:
:number: 24
:text: |2
<span id="LC31" class="line"> <span class="vi">@cmd_output</span> <span class="o">&lt;&lt;</span> <span class="n">stderr</span><span class="p">.</span><span class="nf">read</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_24_31
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 24
+ :new_line: 31
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
:right:
:type:
:number: 31
:text: |2
<span id="LC31" class="line"> <span class="vi">@cmd_output</span> <span class="o">&lt;&lt;</span> <span class="n">stderr</span><span class="p">.</span><span class="nf">read</span></span>
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_24_31
+ :position: !ruby/object:Gitlab::Diff::Position
+ attributes:
+ :old_path: files/ruby/popen.rb
+ :new_path: files/ruby/popen.rb
+ :old_line: 24
+ :new_line: 31
+ :base_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :start_sha: 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ :head_sha: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb
index 52764f41e0d..4b134a48410 100644
--- a/spec/helpers/diff_helper_spec.rb
+++ b/spec/helpers/diff_helper_spec.rb
@@ -9,7 +9,7 @@ describe DiffHelper do
let(:diffs) { commit.diffs }
let(:diff) { diffs.first }
let(:diff_refs) { [commit.parent, commit] }
- let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs) }
+ let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: diff_refs, repository: repository) }
describe 'diff_view' do
it 'returns a valid value when cookie is set' do
@@ -31,26 +31,11 @@ describe DiffHelper do
end
end
- describe 'diff_hard_limit_enabled?' do
- it 'should return true if param is provided' do
- allow(controller).to receive(:params) { { force_show_diff: true } }
- expect(diff_hard_limit_enabled?).to be_truthy
- end
-
- it 'should return false if param is not provided' do
- expect(diff_hard_limit_enabled?).to be_falsey
- end
- end
-
describe 'diff_options' do
- it 'should return hard limit for a diff if force diff is true' do
+ it 'should return hard limit for a diff' do
allow(controller).to receive(:params) { { force_show_diff: true } }
expect(diff_options).to include(Commit.max_diff_options)
end
-
- it 'should return safe limit for a diff if force diff is false' do
- expect(diff_options).not_to include(:max_lines, :max_files)
- end
end
describe 'unfold_bottom_class' do
@@ -59,7 +44,7 @@ describe DiffHelper do
end
it 'should return js class when bottom lines should be unfolded' do
- expect(unfold_bottom_class(true)).to eq('js-unfold-bottom')
+ expect(unfold_bottom_class(true)).to include('js-unfold-bottom')
end
end
diff --git a/spec/helpers/members_helper_spec.rb b/spec/helpers/members_helper_spec.rb
index 7b2155e9a4e..f75fdb739f6 100644
--- a/spec/helpers/members_helper_spec.rb
+++ b/spec/helpers/members_helper_spec.rb
@@ -57,72 +57,6 @@ describe MembersHelper do
end
end
- describe '#can_see_request_access_button?' do
- let(:user) { create(:user) }
- let(:group) { create(:group, :public) }
- let(:project) { create(:project, :public, group: group) }
-
- before do
- allow(helper).to receive(:current_user).and_return(user)
- end
-
- context 'source is a group' do
- context 'current_user is not a member' do
- it 'returns true' do
- expect(helper.can_see_request_access_button?(group)).to be_truthy
- end
- end
-
- context 'current_user is a member' do
- it 'returns false' do
- group.add_owner(user)
-
- expect(helper.can_see_request_access_button?(group)).to be_falsy
- end
- end
-
- context 'current_user is a requester' do
- it 'returns true' do
- group.request_access(user)
-
- expect(helper.can_see_request_access_button?(group)).to be_truthy
- end
- end
- end
-
- context 'source is a project' do
- context 'current_user is not a member' do
- it 'returns true' do
- expect(helper.can_see_request_access_button?(project)).to be_truthy
- end
- end
-
- context 'current_user is a group member' do
- it 'returns false' do
- group.add_owner(user)
-
- expect(helper.can_see_request_access_button?(project)).to be_falsy
- end
- end
-
- context 'current_user is a group requester' do
- it 'returns false' do
- group.request_access(user)
-
- expect(helper.can_see_request_access_button?(project)).to be_falsy
- end
- end
-
- context 'current_user is a member' do
- it 'returns false' do
- project.team << [user, :master]
-
- expect(helper.can_see_request_access_button?(project)).to be_falsy
- end
- end
- end
- end
-
describe '#remove_member_message' do
let(:requester) { build(:user) }
let(:project) { create(:project) }
diff --git a/spec/javascripts/fixtures/issues_show.html.haml b/spec/javascripts/fixtures/issues_show.html.haml
index 470cabeafbb..06c2ab1e823 100644
--- a/spec/javascripts/fixtures/issues_show.html.haml
+++ b/spec/javascripts/fixtures/issues_show.html.haml
@@ -1,7 +1,7 @@
:css
.hidden { display: none !important; }
-.flash-container
+.flash-container.flash-container-page
.flash-alert
.flash-notice
diff --git a/spec/lib/banzai/filter/blockquote_fence_filter_spec.rb b/spec/lib/banzai/filter/blockquote_fence_filter_spec.rb
new file mode 100644
index 00000000000..2799249ae3e
--- /dev/null
+++ b/spec/lib/banzai/filter/blockquote_fence_filter_spec.rb
@@ -0,0 +1,14 @@
+require 'rails_helper'
+
+describe Banzai::Filter::BlockquoteFenceFilter, lib: true do
+ include FilterSpecHelper
+
+ it 'converts blockquote fences to blockquote lines' do
+ content = File.read(Rails.root.join('spec/fixtures/blockquote_fence_before.md'))
+ expected = File.read(Rails.root.join('spec/fixtures/blockquote_fence_after.md'))
+
+ output = filter(content)
+
+ expect(output).to eq(expected)
+ end
+end
diff --git a/spec/lib/banzai/filter/label_reference_filter_spec.rb b/spec/lib/banzai/filter/label_reference_filter_spec.rb
index f1064a701d8..9e3d2f5825d 100644
--- a/spec/lib/banzai/filter/label_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/label_reference_filter_spec.rb
@@ -104,6 +104,31 @@ describe Banzai::Filter::LabelReferenceFilter, lib: true do
end
end
+ context 'String-based single-word references with special characters' do
+ let(:label) { create(:label, name: '?gfm&', project: project) }
+ let(:reference) { "#{Label.reference_prefix}#{label.name}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.
+ namespace_project_issues_url(project.namespace, project, label_name: label.name)
+ expect(doc.text).to eq 'See ?gfm&'
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Label (#{reference}.)")
+ expect(doc.to_html).to match(%r(\(<a.+><span.+>\?gfm&amp;</span></a>\.\)))
+ end
+
+ it 'ignores invalid label names' do
+ act = "Label #{Label.reference_prefix}#{label.name.reverse}"
+ exp = "Label #{Label.reference_prefix}&amp;mfg?"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
context 'String-based multi-word references in quotes' do
let(:label) { create(:label, name: 'gfm references', project: project) }
let(:reference) { label.to_reference(format: :name) }
@@ -128,6 +153,31 @@ describe Banzai::Filter::LabelReferenceFilter, lib: true do
end
end
+ context 'String-based multi-word references with special characters in quotes' do
+ let(:label) { create(:label, name: 'gfm & references?', project: project) }
+ let(:reference) { label.to_reference(format: :name) }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.
+ namespace_project_issues_url(project.namespace, project, label_name: label.name)
+ expect(doc.text).to eq 'See gfm & references?'
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Label (#{reference}.)")
+ expect(doc.to_html).to match(%r(\(<a.+><span.+>gfm &amp; references\?</span></a>\.\)))
+ end
+
+ it 'ignores invalid label names' do
+ act = %(Label #{Label.reference_prefix}"#{label.name.reverse}")
+ exp = %(Label #{Label.reference_prefix}"?secnerefer &amp; mfg\")
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
describe 'edge cases' do
it 'gracefully handles non-references matching the pattern' do
exp = act = '(format nil "~0f" 3.0) ; 3.0'
diff --git a/spec/lib/banzai/object_renderer_spec.rb b/spec/lib/banzai/object_renderer_spec.rb
index 44256b32bdc..d99175967af 100644
--- a/spec/lib/banzai/object_renderer_spec.rb
+++ b/spec/lib/banzai/object_renderer_spec.rb
@@ -17,6 +17,7 @@ describe Banzai::ObjectRenderer do
and_call_original
expect(object).to receive(:note_html=).with('<p>hello</p>')
+ expect(object).to receive(:user_visible_reference_count=).with(0)
renderer.render([object], :note)
end
@@ -25,6 +26,7 @@ describe Banzai::ObjectRenderer do
describe '#render_objects' do
it 'renders an Array of objects' do
object = double(:object, note: 'hello')
+
renderer = described_class.new(project, user)
expect(renderer).to receive(:render_attribute).with(object, :note).
@@ -38,7 +40,7 @@ describe Banzai::ObjectRenderer do
end
describe '#redact_documents' do
- it 'redacts a set of documents and returns them as an Array of Strings' do
+ it 'redacts a set of documents and returns them as an Array of Hashes' do
doc = Nokogiri::HTML.fragment('<p>hello</p>')
renderer = described_class.new(project, user)
@@ -48,7 +50,9 @@ describe Banzai::ObjectRenderer do
redacted = renderer.redact_documents([doc])
- expect(redacted).to eq(['<p>hello</p>'])
+ expect(redacted.count).to eq(1)
+ expect(redacted.first[:visible_reference_count]).to eq(0)
+ expect(redacted.first[:document].to_html).to eq('<p>hello</p>')
end
end
diff --git a/spec/lib/banzai/redactor_spec.rb b/spec/lib/banzai/redactor_spec.rb
index 488f465bcda..254657a881d 100644
--- a/spec/lib/banzai/redactor_spec.rb
+++ b/spec/lib/banzai/redactor_spec.rb
@@ -15,11 +15,31 @@ describe Banzai::Redactor do
expect(redactor).to receive(:nodes_visible_to_user).and_return([])
- expect(redactor.redact([doc1, doc2])).to eq([doc1, doc2])
+ redacted_data = redactor.redact([doc1, doc2])
+ expect(redacted_data.map { |data| data[:document] }).to eq([doc1, doc2])
+ expect(redacted_data.map { |data| data[:visible_reference_count] }).to eq([0, 0])
expect(doc1.to_html).to eq('foo')
expect(doc2.to_html).to eq('bar')
end
+
+ it 'does not redact an Array of documents' do
+ doc1_html = '<a class="gfm" data-reference-type="issue">foo</a>'
+ doc1 = Nokogiri::HTML.fragment(doc1_html)
+
+ doc2_html = '<a class="gfm" data-reference-type="issue">bar</a>'
+ doc2 = Nokogiri::HTML.fragment(doc2_html)
+
+ nodes = redactor.document_nodes([doc1, doc2]).map { |x| x[:nodes] }
+ expect(redactor).to receive(:nodes_visible_to_user).and_return(nodes.flatten)
+
+ redacted_data = redactor.redact([doc1, doc2])
+
+ expect(redacted_data.map { |data| data[:document] }).to eq([doc1, doc2])
+ expect(redacted_data.map { |data| data[:visible_reference_count] }).to eq([1, 1])
+ expect(doc1.to_html).to eq(doc1_html)
+ expect(doc2.to_html).to eq(doc2_html)
+ end
end
describe '#redact_nodes' do
@@ -31,7 +51,7 @@ describe Banzai::Redactor do
with([node]).
and_return(Set.new)
- redactor.redact_nodes([node])
+ redactor.redact_document_nodes([{ document: doc, nodes: [node] }])
expect(doc.to_html).to eq('foo')
end
diff --git a/spec/lib/banzai/reference_parser/base_parser_spec.rb b/spec/lib/banzai/reference_parser/base_parser_spec.rb
index 543b4786d84..ac9c66e2663 100644
--- a/spec/lib/banzai/reference_parser/base_parser_spec.rb
+++ b/spec/lib/banzai/reference_parser/base_parser_spec.rb
@@ -234,4 +234,79 @@ describe Banzai::ReferenceParser::BaseParser, lib: true do
to eq([project])
end
end
+
+ describe '#collection_objects_for_ids' do
+ context 'with RequestStore disabled' do
+ it 'queries the collection directly' do
+ collection = User.all
+
+ expect(collection).to receive(:where).twice.and_call_original
+
+ 2.times do
+ expect(subject.collection_objects_for_ids(collection, [user.id])).
+ to eq([user])
+ end
+ end
+ end
+
+ context 'with RequestStore enabled' 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
+
+ it 'queries the collection on the first call' do
+ expect(subject.collection_objects_for_ids(User, [user.id])).
+ to eq([user])
+ end
+
+ it 'does not query previously queried objects' do
+ collection = User.all
+
+ expect(collection).to receive(:where).once.and_call_original
+
+ 2.times do
+ expect(subject.collection_objects_for_ids(collection, [user.id])).
+ to eq([user])
+ end
+ end
+
+ it 'casts String based IDs to Fixnums before querying objects' do
+ 2.times do
+ expect(subject.collection_objects_for_ids(User, [user.id.to_s])).
+ to eq([user])
+ end
+ end
+
+ it 'queries any additional objects after the first call' do
+ other_user = create(:user)
+
+ expect(subject.collection_objects_for_ids(User, [user.id])).
+ to eq([user])
+
+ expect(subject.collection_objects_for_ids(User, [user.id, other_user.id])).
+ to eq([user, other_user])
+ end
+
+ it 'caches objects on a per collection class basis' do
+ expect(subject.collection_objects_for_ids(User, [user.id])).
+ to eq([user])
+
+ expect(subject.collection_objects_for_ids(Project, [project.id])).
+ to eq([project])
+ end
+ end
+ end
+
+ describe '#collection_cache_key' do
+ it 'returns the cache key for a Class' do
+ expect(subject.collection_cache_key(Project)).to eq(Project)
+ end
+
+ it 'returns the cache key for an ActiveRecord::Relation' do
+ expect(subject.collection_cache_key(Project.all)).to eq(Project)
+ end
+ end
end
diff --git a/spec/lib/gitlab/diff/file_spec.rb b/spec/lib/gitlab/diff/file_spec.rb
index a0cbef6e6a4..1cb513d5229 100644
--- a/spec/lib/gitlab/diff/file_spec.rb
+++ b/spec/lib/gitlab/diff/file_spec.rb
@@ -6,7 +6,7 @@ describe Gitlab::Diff::File, lib: true do
let(:project) { create(:project) }
let(:commit) { project.commit(sample_commit.id) }
let(:diff) { commit.diffs.first }
- let(:diff_file) { Gitlab::Diff::File.new(diff, [commit.parent, commit]) }
+ let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: commit.diff_refs, repository: project.repository) }
describe :diff_lines do
let(:diff_lines) { diff_file.diff_lines }
diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb
index d19bf4ac84b..fb5d50a5c68 100644
--- a/spec/lib/gitlab/diff/highlight_spec.rb
+++ b/spec/lib/gitlab/diff/highlight_spec.rb
@@ -6,11 +6,11 @@ describe Gitlab::Diff::Highlight, lib: true do
let(:project) { create(:project) }
let(:commit) { project.commit(sample_commit.id) }
let(:diff) { commit.diffs.first }
- let(:diff_file) { Gitlab::Diff::File.new(diff, [commit.parent, commit]) }
+ let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: commit.diff_refs, repository: project.repository) }
describe '#highlight' do
context "with a diff file" do
- let(:subject) { Gitlab::Diff::Highlight.new(diff_file).highlight }
+ let(:subject) { Gitlab::Diff::Highlight.new(diff_file, repository: project.repository).highlight }
it 'should return Gitlab::Diff::Line elements' do
expect(subject.first).to be_an_instance_of(Gitlab::Diff::Line)
@@ -41,7 +41,7 @@ describe Gitlab::Diff::Highlight, lib: true do
end
context "with diff lines" do
- let(:subject) { Gitlab::Diff::Highlight.new(diff_file.diff_lines).highlight }
+ let(:subject) { Gitlab::Diff::Highlight.new(diff_file.diff_lines, repository: project.repository).highlight }
it 'should return Gitlab::Diff::Line elements' do
expect(subject.first).to be_an_instance_of(Gitlab::Diff::Line)
diff --git a/spec/lib/gitlab/diff/line_mapper_spec.rb b/spec/lib/gitlab/diff/line_mapper_spec.rb
new file mode 100644
index 00000000000..4e50e03bb7e
--- /dev/null
+++ b/spec/lib/gitlab/diff/line_mapper_spec.rb
@@ -0,0 +1,137 @@
+require 'spec_helper'
+
+describe Gitlab::Diff::LineMapper, lib: true do
+ include RepoHelpers
+
+ let(:project) { create(:project) }
+ let(:repository) { project.repository }
+ let(:commit) { project.commit(sample_commit.id) }
+ let(:diffs) { commit.diffs }
+ let(:diff) { diffs.first }
+ let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: commit.diff_refs, repository: repository) }
+ subject { described_class.new(diff_file) }
+
+ describe '#old_to_new' do
+ context "with a diff file" do
+ let(:mapping) do
+ {
+ 1 => 1,
+ 2 => 2,
+ 3 => 3,
+ 4 => 4,
+ 5 => 5,
+ 6 => 6,
+ 7 => 7,
+ 8 => 8,
+ 9 => nil,
+ # nil => 9,
+ 10 => 10,
+ 11 => 11,
+ 12 => 12,
+ 13 => nil,
+ 14 => nil,
+ # nil => 15,
+ # nil => 16,
+ # nil => 17,
+ # nil => 18,
+ # nil => 19,
+ # nil => 20,
+ 15 => 21,
+ 16 => 22,
+ 17 => 23,
+ 18 => 24,
+ 19 => 25,
+ 20 => 26,
+ 21 => 27,
+ # nil => 28,
+ 22 => 29,
+ 23 => 30,
+ 24 => 31,
+ 25 => 32,
+ 26 => 33,
+ 27 => 34,
+ 28 => 35,
+ 29 => 36,
+ 30 => 37
+ }
+ end
+
+ it 'returns the new line number for the old line number' do
+ mapping.each do |old_line, new_line|
+ expect(subject.old_to_new(old_line)).to eq(new_line)
+ end
+ end
+ end
+
+ context "without a diff file" do
+ let(:diff_file) { nil }
+
+ it "returns the same line number" do
+ expect(subject.old_to_new(100)).to eq(100)
+ end
+ end
+ end
+
+ describe '#new_to_old' do
+ context "with a diff file" do
+ let(:mapping) do
+ {
+ 1 => 1,
+ 2 => 2,
+ 3 => 3,
+ 4 => 4,
+ 5 => 5,
+ 6 => 6,
+ 7 => 7,
+ 8 => 8,
+ # nil => 9,
+ 9 => nil,
+ 10 => 10,
+ 11 => 11,
+ 12 => 12,
+ # nil => 13,
+ # nil => 14,
+ 13 => nil,
+ 14 => nil,
+ 15 => nil,
+ 16 => nil,
+ 17 => nil,
+ 18 => nil,
+ 19 => nil,
+ 20 => nil,
+ 21 => 15,
+ 22 => 16,
+ 23 => 17,
+ 24 => 18,
+ 25 => 19,
+ 26 => 20,
+ 27 => 21,
+ 28 => nil,
+ 29 => 22,
+ 30 => 23,
+ 31 => 24,
+ 32 => 25,
+ 33 => 26,
+ 34 => 27,
+ 35 => 28,
+ 36 => 29,
+ 37 => 30
+ }
+ end
+
+ it 'returns the old line number for the new line number' do
+ mapping.each do |new_line, old_line|
+ expect(subject.new_to_old(new_line)).to eq(old_line)
+ end
+ end
+ end
+
+ context "without a diff file" do
+ let(:diff_file) { nil }
+
+ it "returns the same line number" do
+ expect(subject.new_to_old(100)).to eq(100)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/diff/parallel_diff_spec.rb b/spec/lib/gitlab/diff/parallel_diff_spec.rb
index 1c5bbc47120..5f76b70c6f5 100644
--- a/spec/lib/gitlab/diff/parallel_diff_spec.rb
+++ b/spec/lib/gitlab/diff/parallel_diff_spec.rb
@@ -8,8 +8,7 @@ describe Gitlab::Diff::ParallelDiff, lib: true do
let(:commit) { project.commit(sample_commit.id) }
let(:diffs) { commit.diffs }
let(:diff) { diffs.first }
- let(:diff_refs) { [commit.parent, commit] }
- let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs) }
+ let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: commit.diff_refs, repository: repository) }
subject { described_class.new(diff_file) }
let(:parallel_diff_result_array) { YAML.load_file("#{Rails.root}/spec/fixtures/parallel_diff_result.yml") }
diff --git a/spec/lib/gitlab/diff/position_spec.rb b/spec/lib/gitlab/diff/position_spec.rb
new file mode 100644
index 00000000000..cf28628cb96
--- /dev/null
+++ b/spec/lib/gitlab/diff/position_spec.rb
@@ -0,0 +1,341 @@
+require 'spec_helper'
+
+describe Gitlab::Diff::Position, lib: true do
+ include RepoHelpers
+
+ let(:project) { create(:project) }
+
+ describe "position for an added file" do
+ let(:commit) { project.commit("2ea1f3dec713d940208fb5ce4a38765ecb5d3f73") }
+
+ subject do
+ described_class.new(
+ old_path: "files/images/wm.svg",
+ new_path: "files/images/wm.svg",
+ old_line: nil,
+ new_line: 5,
+ diff_refs: commit.diff_refs
+ )
+ end
+
+ describe "#diff_file" do
+ it "returns the correct diff file" do
+ diff_file = subject.diff_file(project.repository)
+
+ expect(diff_file.new_file).to be true
+ expect(diff_file.new_path).to eq(subject.new_path)
+ expect(diff_file.diff_refs).to eq(subject.diff_refs)
+ end
+ end
+
+ describe "#diff_line" do
+ it "returns the correct diff line" do
+ diff_line = subject.diff_line(project.repository)
+
+ expect(diff_line.added?).to be true
+ expect(diff_line.new_line).to eq(subject.new_line)
+ expect(diff_line.text).to eq("+ <desc>Created with Sketch.</desc>")
+ end
+ end
+
+ describe "#line_code" do
+ it "returns the correct line code" do
+ line_code = Gitlab::Diff::LineCode.generate(subject.file_path, subject.new_line, 0)
+
+ expect(subject.line_code(project.repository)).to eq(line_code)
+ end
+ end
+ end
+
+ describe "position for a changed file" do
+ let(:commit) { project.commit("570e7b2abdd848b95f2f578043fc23bd6f6fd24d") }
+
+ describe "position for an added line" do
+ subject do
+ described_class.new(
+ old_path: "files/ruby/popen.rb",
+ new_path: "files/ruby/popen.rb",
+ old_line: nil,
+ new_line: 14,
+ diff_refs: commit.diff_refs
+ )
+ end
+
+ describe "#diff_file" do
+ it "returns the correct diff file" do
+ diff_file = subject.diff_file(project.repository)
+
+ expect(diff_file.old_path).to eq(subject.old_path)
+ expect(diff_file.new_path).to eq(subject.new_path)
+ expect(diff_file.diff_refs).to eq(subject.diff_refs)
+ end
+ end
+
+ describe "#diff_line" do
+ it "returns the correct diff line" do
+ diff_line = subject.diff_line(project.repository)
+
+ expect(diff_line.added?).to be true
+ expect(diff_line.new_line).to eq(subject.new_line)
+ expect(diff_line.text).to eq("+ vars = {")
+ end
+ end
+
+ describe "#line_code" do
+ it "returns the correct line code" do
+ line_code = Gitlab::Diff::LineCode.generate(subject.file_path, subject.new_line, 15)
+
+ expect(subject.line_code(project.repository)).to eq(line_code)
+ end
+ end
+ end
+
+ describe "position for an unchanged line" do
+ subject do
+ described_class.new(
+ old_path: "files/ruby/popen.rb",
+ new_path: "files/ruby/popen.rb",
+ old_line: 16,
+ new_line: 22,
+ diff_refs: commit.diff_refs
+ )
+ end
+
+ describe "#diff_file" do
+ it "returns the correct diff file" do
+ diff_file = subject.diff_file(project.repository)
+
+ expect(diff_file.old_path).to eq(subject.old_path)
+ expect(diff_file.new_path).to eq(subject.new_path)
+ expect(diff_file.diff_refs).to eq(subject.diff_refs)
+ end
+ end
+
+ describe "#diff_line" do
+ it "returns the correct diff line" do
+ diff_line = subject.diff_line(project.repository)
+
+ expect(diff_line.unchanged?).to be true
+ expect(diff_line.old_line).to eq(subject.old_line)
+ expect(diff_line.new_line).to eq(subject.new_line)
+ expect(diff_line.text).to eq(" unless File.directory?(path)")
+ end
+ end
+
+ describe "#line_code" do
+ it "returns the correct line code" do
+ line_code = Gitlab::Diff::LineCode.generate(subject.file_path, subject.new_line, subject.old_line)
+
+ expect(subject.line_code(project.repository)).to eq(line_code)
+ end
+ end
+ end
+
+ describe "position for a removed line" do
+ subject do
+ described_class.new(
+ old_path: "files/ruby/popen.rb",
+ new_path: "files/ruby/popen.rb",
+ old_line: 14,
+ new_line: nil,
+ diff_refs: commit.diff_refs
+ )
+ end
+
+ describe "#diff_file" do
+ it "returns the correct diff file" do
+ diff_file = subject.diff_file(project.repository)
+
+ expect(diff_file.old_path).to eq(subject.old_path)
+ expect(diff_file.new_path).to eq(subject.new_path)
+ expect(diff_file.diff_refs).to eq(subject.diff_refs)
+ end
+ end
+
+ describe "#diff_line" do
+ it "returns the correct diff line" do
+ diff_line = subject.diff_line(project.repository)
+
+ expect(diff_line.removed?).to be true
+ expect(diff_line.old_line).to eq(subject.old_line)
+ expect(diff_line.text).to eq("- options = { chdir: path }")
+ end
+ end
+
+ describe "#line_code" do
+ it "returns the correct line code" do
+ line_code = Gitlab::Diff::LineCode.generate(subject.file_path, 13, subject.old_line)
+
+ expect(subject.line_code(project.repository)).to eq(line_code)
+ end
+ end
+ end
+ end
+
+ describe "position for a renamed file" do
+ let(:commit) { project.commit("6907208d755b60ebeacb2e9dfea74c92c3449a1f") }
+
+ describe "position for an added line" do
+ subject do
+ described_class.new(
+ old_path: "files/js/commit.js.coffee",
+ new_path: "files/js/commit.coffee",
+ old_line: nil,
+ new_line: 4,
+ diff_refs: commit.diff_refs
+ )
+ end
+
+ describe "#diff_file" do
+ it "returns the correct diff file" do
+ diff_file = subject.diff_file(project.repository)
+
+ expect(diff_file.old_path).to eq(subject.old_path)
+ expect(diff_file.new_path).to eq(subject.new_path)
+ expect(diff_file.diff_refs).to eq(subject.diff_refs)
+ end
+ end
+
+ describe "#diff_line" do
+ it "returns the correct diff line" do
+ diff_line = subject.diff_line(project.repository)
+
+ expect(diff_line.added?).to be true
+ expect(diff_line.new_line).to eq(subject.new_line)
+ expect(diff_line.text).to eq("+ new CommitFile(@)")
+ end
+ end
+
+ describe "#line_code" do
+ it "returns the correct line code" do
+ line_code = Gitlab::Diff::LineCode.generate(subject.file_path, subject.new_line, 5)
+
+ expect(subject.line_code(project.repository)).to eq(line_code)
+ end
+ end
+ end
+
+ describe "position for an unchanged line" do
+ subject do
+ described_class.new(
+ old_path: "files/js/commit.js.coffee",
+ new_path: "files/js/commit.coffee",
+ old_line: 3,
+ new_line: 3,
+ diff_refs: commit.diff_refs
+ )
+ end
+
+ describe "#diff_file" do
+ it "returns the correct diff file" do
+ diff_file = subject.diff_file(project.repository)
+
+ expect(diff_file.old_path).to eq(subject.old_path)
+ expect(diff_file.new_path).to eq(subject.new_path)
+ expect(diff_file.diff_refs).to eq(subject.diff_refs)
+ end
+ end
+
+ describe "#diff_line" do
+ it "returns the correct diff line" do
+ diff_line = subject.diff_line(project.repository)
+
+ expect(diff_line.unchanged?).to be true
+ expect(diff_line.old_line).to eq(subject.old_line)
+ expect(diff_line.new_line).to eq(subject.new_line)
+ expect(diff_line.text).to eq(" $('.files .diff-file').each ->")
+ end
+ end
+
+ describe "#line_code" do
+ it "returns the correct line code" do
+ line_code = Gitlab::Diff::LineCode.generate(subject.file_path, subject.new_line, subject.old_line)
+
+ expect(subject.line_code(project.repository)).to eq(line_code)
+ end
+ end
+ end
+
+ describe "position for a removed line" do
+ subject do
+ described_class.new(
+ old_path: "files/js/commit.js.coffee",
+ new_path: "files/js/commit.coffee",
+ old_line: 4,
+ new_line: nil,
+ diff_refs: commit.diff_refs
+ )
+ end
+
+ describe "#diff_file" do
+ it "returns the correct diff file" do
+ diff_file = subject.diff_file(project.repository)
+
+ expect(diff_file.old_path).to eq(subject.old_path)
+ expect(diff_file.new_path).to eq(subject.new_path)
+ expect(diff_file.diff_refs).to eq(subject.diff_refs)
+ end
+ end
+
+ describe "#diff_line" do
+ it "returns the correct diff line" do
+ diff_line = subject.diff_line(project.repository)
+
+ expect(diff_line.removed?).to be true
+ expect(diff_line.old_line).to eq(subject.old_line)
+ expect(diff_line.text).to eq("- new CommitFile(this)")
+ end
+ end
+
+ describe "#line_code" do
+ it "returns the correct line code" do
+ line_code = Gitlab::Diff::LineCode.generate(subject.file_path, 4, subject.old_line)
+
+ expect(subject.line_code(project.repository)).to eq(line_code)
+ end
+ end
+ end
+ end
+
+ describe "position for a deleted file" do
+ let(:commit) { project.commit("8634272bfad4cf321067c3e94d64d5a253f8321d") }
+
+ subject do
+ described_class.new(
+ old_path: "LICENSE",
+ new_path: "LICENSE",
+ old_line: 3,
+ new_line: nil,
+ diff_refs: commit.diff_refs
+ )
+ end
+
+ describe "#diff_file" do
+ it "returns the correct diff file" do
+ diff_file = subject.diff_file(project.repository)
+
+ expect(diff_file.deleted_file).to be true
+ expect(diff_file.old_path).to eq(subject.old_path)
+ expect(diff_file.diff_refs).to eq(subject.diff_refs)
+ end
+ end
+
+ describe "#diff_line" do
+ it "returns the correct diff line" do
+ diff_line = subject.diff_line(project.repository)
+
+ expect(diff_line.removed?).to be true
+ expect(diff_line.old_line).to eq(subject.old_line)
+ expect(diff_line.text).to eq("-Copyright (c) 2014 gitlabhq")
+ end
+ end
+
+ describe "#line_code" do
+ it "returns the correct line code" do
+ line_code = Gitlab::Diff::LineCode.generate(subject.file_path, 0, subject.old_line)
+
+ expect(subject.line_code(project.repository)).to eq(line_code)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/diff/position_tracer_spec.rb b/spec/lib/gitlab/diff/position_tracer_spec.rb
new file mode 100644
index 00000000000..08312e60f4a
--- /dev/null
+++ b/spec/lib/gitlab/diff/position_tracer_spec.rb
@@ -0,0 +1,1758 @@
+require 'spec_helper'
+
+describe Gitlab::Diff::PositionTracer, lib: true do
+ # Douwe's diary New York City, 2016-06-28
+ # --------------------------------------------------------------------------
+ #
+ # Dear diary,
+ #
+ # Ideally, we would have a test for every single diff scenario that can
+ # occur and that the PositionTracer should correctly trace a position
+ # through, across the following variables:
+ #
+ # - Old diff file type: created, changed, renamed, deleted, unchanged (5)
+ # - Old diff line type: added, removed, unchanged (3)
+ # - New diff file type: created, changed, renamed, deleted, unchanged (5)
+ # - New diff line type: added, removed, unchanged (3)
+ # - Old-to-new diff line change: kept, moved, undone (3)
+ #
+ # This adds up to 5 * 3 * 5 * 3 * 3 = 675 different potential scenarios,
+ # and 675 different tests to cover them all. In reality, it would be fewer,
+ # since one cannot have a removed line in a created file diff, for example,
+ # but for the sake of this diary entry, let's be pessimistic.
+ #
+ # Writing these tests is a manual and time consuming process, as every test
+ # requires the manual construction or finding of a combination of diffs that
+ # create the exact diff scenario we are looking for, and can take between
+ # 1 and 10 minutes, depending on the farfetchedness of the scenario and
+ # complexity of creating it.
+ #
+ # This means that writing tests to cover all of these scenarios would end up
+ # taking between 11 and 112 hours in total, which I do not believe is the
+ # best use of my time.
+ #
+ # A better course of action would be to think of scenarios that are likely
+ # to occur, but also potentially tricky to trace correctly, and only cover
+ # those, with a few more obvious scenarios thrown in to cover our bases.
+ #
+ # Unfortunately, I only came to the above realization once I was about
+ # 1/5th of the way through the process of writing ALL THE SPECS, having
+ # already wasted about 3 hours trying to be thorough.
+ #
+ # I did find 2 bugs while writing those though, so that's good.
+ #
+ # 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
+ # testing of other scenarios.
+ #
+ # I did still try to cover most of the obvious and potentially tricky
+ # scenarios, though.
+
+ include RepoHelpers
+
+ let(:project) { create(:project) }
+ let(:current_user) { project.owner }
+ let(:repository) { project.repository }
+ let(:file_name) { "test-file" }
+ let(:new_file_name) { "#{file_name}-new" }
+ let(:second_file_name) { "#{file_name}-2" }
+ let(:branch_name) { "position-tracer-test" }
+
+ let(:old_diff_refs) { raise NotImplementedError }
+ let(:new_diff_refs) { raise NotImplementedError }
+ let(:old_position) { raise NotImplementedError }
+
+ let(:position_tracer) { described_class.new(repository: project.repository, old_diff_refs: old_diff_refs, new_diff_refs: new_diff_refs) }
+ subject { position_tracer.trace(old_position) }
+
+ def diff_refs(base_commit, head_commit)
+ Gitlab::Diff::DiffRefs.new(base_sha: base_commit.id, head_sha: head_commit.id)
+ end
+
+ def position(attrs = {})
+ attrs.reverse_merge!(
+ diff_refs: old_diff_refs
+ )
+ Gitlab::Diff::Position.new(attrs)
+ end
+
+ def expect_new_position(attrs, new_position = subject)
+ if attrs.nil?
+ expect(new_position).to be_nil
+ else
+ expect(new_position).not_to be_nil
+
+ expect(new_position.diff_refs).to eq(new_diff_refs)
+
+ attrs.each do |attr, value|
+ expect(new_position.send(attr)).to eq(value)
+ end
+ end
+ end
+
+ def create_branch(new_name, branch_name)
+ CreateBranchService.new(project, current_user).execute(new_name, branch_name)
+ end
+
+ def create_file(branch_name, file_name, content)
+ Files::CreateService.new(
+ project,
+ current_user,
+ source_branch: branch_name,
+ target_branch: branch_name,
+ commit_message: "Create file",
+ file_path: file_name,
+ file_content: content
+ ).execute
+ project.commit(branch_name)
+ end
+
+ def update_file(branch_name, file_name, content)
+ Files::UpdateService.new(
+ project,
+ current_user,
+ source_branch: branch_name,
+ target_branch: branch_name,
+ commit_message: "Update file",
+ file_path: file_name,
+ file_content: content
+ ).execute
+ project.commit(branch_name)
+ end
+
+ def delete_file(branch_name, file_name)
+ Files::DeleteService.new(
+ project,
+ current_user,
+ source_branch: branch_name,
+ target_branch: branch_name,
+ commit_message: "Delete file",
+ file_path: file_name
+ ).execute
+ project.commit(branch_name)
+ end
+
+ let(:initial_commit) do
+ create_branch(branch_name, "master")[:branch].name
+ project.commit(branch_name)
+ end
+
+ describe "#trace" do
+ describe "diff scenarios" do
+ let(:create_file_commit) do
+ initial_commit
+
+ create_file(
+ branch_name,
+ file_name,
+ <<-CONTENT.strip_heredoc
+ A
+ B
+ C
+ CONTENT
+ )
+ end
+
+ let(:create_second_file_commit) do
+ create_file_commit
+
+ create_file(
+ branch_name,
+ second_file_name,
+ <<-CONTENT.strip_heredoc
+ D
+ E
+ CONTENT
+ )
+ end
+
+ let(:update_line_commit) do
+ create_second_file_commit
+
+ update_file(
+ branch_name,
+ file_name,
+ <<-CONTENT.strip_heredoc
+ A
+ BB
+ C
+ CONTENT
+ )
+ end
+
+ let(:update_second_file_line_commit) do
+ update_line_commit
+
+ update_file(
+ branch_name,
+ second_file_name,
+ <<-CONTENT.strip_heredoc
+ D
+ EE
+ CONTENT
+ )
+ end
+
+ let(:move_line_commit) do
+ update_second_file_line_commit
+
+ update_file(
+ branch_name,
+ file_name,
+ <<-CONTENT.strip_heredoc
+ BB
+ A
+ C
+ CONTENT
+ )
+ end
+
+ let(:add_second_file_line_commit) do
+ move_line_commit
+
+ update_file(
+ branch_name,
+ second_file_name,
+ <<-CONTENT.strip_heredoc
+ D
+ EE
+ F
+ CONTENT
+ )
+ end
+
+ let(:move_second_file_line_commit) do
+ add_second_file_line_commit
+
+ update_file(
+ branch_name,
+ second_file_name,
+ <<-CONTENT.strip_heredoc
+ D
+ F
+ EE
+ CONTENT
+ )
+ end
+
+ let(:delete_line_commit) do
+ move_second_file_line_commit
+
+ update_file(
+ branch_name,
+ file_name,
+ <<-CONTENT.strip_heredoc
+ BB
+ A
+ CONTENT
+ )
+ end
+
+ let(:delete_second_file_line_commit) do
+ delete_line_commit
+
+ update_file(
+ branch_name,
+ second_file_name,
+ <<-CONTENT.strip_heredoc
+ D
+ F
+ CONTENT
+ )
+ end
+
+ let(:delete_file_commit) do
+ delete_second_file_line_commit
+
+ delete_file(branch_name, file_name)
+ end
+
+ let(:rename_file_commit) do
+ delete_file_commit
+
+ create_file(
+ branch_name,
+ new_file_name,
+ <<-CONTENT.strip_heredoc
+ BB
+ A
+ CONTENT
+ )
+ end
+
+ let(:update_line_again_commit) do
+ rename_file_commit
+
+ update_file(
+ branch_name,
+ new_file_name,
+ <<-CONTENT.strip_heredoc
+ BB
+ AA
+ CONTENT
+ )
+ end
+
+ let(:move_line_again_commit) do
+ update_line_again_commit
+
+ update_file(
+ branch_name,
+ new_file_name,
+ <<-CONTENT.strip_heredoc
+ AA
+ BB
+ CONTENT
+ )
+ end
+
+ let(:delete_line_again_commit) do
+ move_line_again_commit
+
+ update_file(
+ branch_name,
+ new_file_name,
+ <<-CONTENT.strip_heredoc
+ AA
+ CONTENT
+ )
+ end
+
+ context "when the file was created in the old diff" do
+ context "when the file is created in the new diff" do
+ context "when the position pointed at an added line in the old diff" do
+ context "when the file's content was unchanged between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
+ let(:new_diff_refs) { diff_refs(initial_commit, create_second_file_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 2) }
+
+ # old diff:
+ # 1 + A
+ # 2 + B
+ # 3 + C
+ #
+ # new diff:
+ # 1 + A
+ # 2 + B
+ # 3 + C
+
+ it "returns the new position" do
+ expect_new_position(
+ new_path: old_position.new_path,
+ new_line: old_position.new_line
+ )
+ end
+ end
+
+ context "when the file's content was changed between the old and the new diff" do
+ context "when that line was unchanged between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
+ let(:new_diff_refs) { diff_refs(initial_commit, update_line_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 1) }
+
+ # old diff:
+ # 1 + A
+ # 2 + B
+ # 3 + C
+ #
+ # new diff:
+ # 1 + A
+ # 2 + BB
+ # 3 + C
+
+ it "returns the new position" do
+ expect_new_position(
+ new_path: old_position.new_path,
+ new_line: old_position.new_line
+ )
+ end
+ end
+
+ context "when that line was moved between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, update_line_commit) }
+ let(:new_diff_refs) { diff_refs(initial_commit, move_line_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 2) }
+
+ # old diff:
+ # 1 + A
+ # 2 + BB
+ # 3 + C
+ #
+ # new diff:
+ # 1 + BB
+ # 2 + A
+ # 3 + C
+
+ it "returns the new position" do
+ expect_new_position(
+ new_path: old_position.new_path,
+ new_line: 1
+ )
+ end
+ end
+
+ context "when that line was changed between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
+ let(:new_diff_refs) { diff_refs(initial_commit, update_line_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 2) }
+
+ # old diff:
+ # 1 + A
+ # 2 + B
+ # 3 + C
+ #
+ # new diff:
+ # 1 + A
+ # 2 + BB
+ # 3 + C
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+
+ context "when that line was deleted between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, update_line_commit) }
+ let(:new_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 3) }
+
+ # old diff:
+ # 1 + A
+ # 2 + BB
+ # 3 + C
+ #
+ # new diff:
+ # 1 + A
+ # 2 + BB
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+ end
+ end
+ end
+
+ context "when the file is changed in the new diff" do
+ context "when the position pointed at an added line in the old diff" do
+ context "when the file's content was unchanged between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, update_line_commit) }
+ let(:new_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 1) }
+
+ # old diff:
+ # 1 + A
+ # 2 + BB
+ # 3 + C
+ #
+ # new diff:
+ # 1 1 A
+ # 2 - B
+ # 2 + BB
+ # 3 3 C
+
+ it "returns the new position" do
+ expect_new_position(
+ new_path: old_position.new_path,
+ new_line: old_position.new_line
+ )
+ end
+ end
+
+ context "when the file's content was changed between the old and the new diff" do
+ context "when that line was unchanged between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, update_line_commit) }
+ let(:new_diff_refs) { diff_refs(update_line_commit, move_line_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 3) }
+
+ # old diff:
+ # 1 + A
+ # 2 + BB
+ # 3 + C
+ #
+ # new diff:
+ # 1 - A
+ # 2 1 BB
+ # 2 + A
+ # 3 3 C
+
+ it "returns the new position" do
+ expect_new_position(
+ new_path: old_position.new_path,
+ new_line: old_position.new_line
+ )
+ end
+ end
+
+ context "when that line was moved between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, update_line_commit) }
+ let(:new_diff_refs) { diff_refs(update_line_commit, move_line_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 2) }
+
+ # old diff:
+ # 1 + A
+ # 2 + BB
+ # 3 + C
+ #
+ # new diff:
+ # 1 - A
+ # 2 1 BB
+ # 2 + A
+ # 3 3 C
+
+ it "returns the new position" do
+ expect_new_position(
+ new_path: old_position.new_path,
+ new_line: 1
+ )
+ end
+ end
+
+ context "when that line was changed between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
+ let(:new_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 2) }
+
+ # old diff:
+ # 1 + A
+ # 2 + B
+ # 3 + C
+ #
+ # new diff:
+ # 1 1 A
+ # 2 - B
+ # 2 + BB
+ # 3 3 C
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+
+ context "when that line was deleted between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, move_line_commit) }
+ let(:new_diff_refs) { diff_refs(move_line_commit, delete_line_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 3) }
+
+ # old diff:
+ # 1 + BB
+ # 2 + A
+ # 3 + C
+ #
+ # new diff:
+ # 1 1 BB
+ # 2 2 A
+ # 3 - C
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+ end
+ end
+ end
+
+ context "when the file is renamed in the new diff" do
+ context "when the position pointed at an added line in the old diff" do
+ context "when the file's content was unchanged between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
+ let(:new_diff_refs) { diff_refs(delete_line_commit, rename_file_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 2) }
+
+ # old diff:
+ # 1 + BB
+ # 2 + A
+ #
+ # new diff:
+ # file_name -> new_file_name
+ # 1 1 BB
+ # 2 2 A
+
+ it "returns the new position" do
+ expect_new_position(
+ old_path: file_name,
+ new_path: new_file_name,
+ old_line: old_position.new_line,
+ new_line: old_position.new_line
+ )
+ end
+ end
+
+ context "when the file's content was changed between the old and the new diff" do
+ context "when that line was unchanged between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
+ let(:new_diff_refs) { diff_refs(delete_line_commit, update_line_again_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 1) }
+
+ # old diff:
+ # 1 + BB
+ # 2 + A
+ #
+ # new diff:
+ # file_name -> new_file_name
+ # 1 1 BB
+ # 2 - A
+ # 2 + AA
+
+ it "returns the new position" do
+ expect_new_position(
+ old_path: file_name,
+ new_path: new_file_name,
+ old_line: old_position.new_line,
+ new_line: old_position.new_line
+ )
+ end
+ end
+
+ context "when that line was moved between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
+ let(:new_diff_refs) { diff_refs(delete_line_commit, move_line_again_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 1) }
+
+ # old diff:
+ # 1 + BB
+ # 2 + A
+ #
+ # new diff:
+ # file_name -> new_file_name
+ # 1 + AA
+ # 1 2 BB
+ # 2 - A
+
+ it "returns the new position" do
+ expect_new_position(
+ old_path: file_name,
+ new_path: new_file_name,
+ old_line: 1,
+ new_line: 2
+ )
+ end
+ end
+
+ context "when that line was changed between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
+ let(:new_diff_refs) { diff_refs(delete_line_commit, update_line_again_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 2) }
+
+ # old diff:
+ # 1 + BB
+ # 2 + A
+ #
+ # new diff:
+ # file_name -> new_file_name
+ # 1 1 BB
+ # 2 - A
+ # 2 + AA
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+
+ context "when that line was deleted between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
+ let(:new_diff_refs) { diff_refs(delete_line_commit, delete_line_again_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 1) }
+
+ # old diff:
+ # 1 + BB
+ # 2 + A
+ #
+ # new diff:
+ # file_name -> new_file_name
+ # 1 - BB
+ # 2 - A
+ # 1 + AA
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+ end
+ end
+ end
+
+ context "when the file is deleted in the new diff" do
+ context "when the position pointed at an added line in the old diff" do
+ context "when the file's content was unchanged between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
+ let(:new_diff_refs) { diff_refs(delete_line_commit, delete_file_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 2) }
+
+ # old diff:
+ # 1 + BB
+ # 2 + A
+ #
+ # new diff:
+ # 1 - BB
+ # 2 - A
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+
+ context "when the file's content was changed between the old and the new diff" do
+ context "when that line was unchanged between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, move_line_commit) }
+ let(:new_diff_refs) { diff_refs(delete_line_commit, delete_file_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 2) }
+
+ # old diff:
+ # 1 + BB
+ # 2 + A
+ # 3 + C
+ #
+ # new diff:
+ # 1 - BB
+ # 2 - A
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+
+ context "when that line was moved between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, update_line_commit) }
+ let(:new_diff_refs) { diff_refs(move_line_commit, delete_file_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 2) }
+
+ # old diff:
+ # 1 + A
+ # 2 + BB
+ # 3 + C
+ #
+ # new diff:
+ # 1 - BB
+ # 2 - A
+ # 3 - C
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+
+ context "when that line was changed between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
+ let(:new_diff_refs) { diff_refs(update_line_commit, delete_file_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 2) }
+
+ # old diff:
+ # 1 + A
+ # 2 + B
+ # 3 + C
+ #
+ # new diff:
+ # 1 - A
+ # 2 - BB
+ # 3 - C
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+
+ context "when that line was deleted between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, move_line_commit) }
+ let(:new_diff_refs) { diff_refs(delete_line_commit, delete_file_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 3) }
+
+ # old diff:
+ # 1 + BB
+ # 2 + A
+ # 3 + C
+ #
+ # new diff:
+ # 1 - BB
+ # 2 - A
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+ end
+ end
+ end
+
+ context "when the file is unchanged in the new diff" do
+ context "when the position pointed at an added line in the old diff" do
+ context "when the file's content was unchanged between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
+ let(:new_diff_refs) { diff_refs(create_file_commit, create_second_file_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 2) }
+
+ # old diff:
+ # 1 + A
+ # 2 + B
+ # 3 + C
+ #
+ # new diff:
+ # 1 1 A
+ # 2 2 B
+ # 3 3 C
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+
+ context "when the file's content was changed between the old and the new diff" do
+ context "when that line was unchanged between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
+ let(:new_diff_refs) { diff_refs(update_line_commit, update_second_file_line_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 1) }
+
+ # old diff:
+ # 1 + A
+ # 2 + B
+ # 3 + C
+ #
+ # new diff:
+ # 1 1 A
+ # 2 2 BB
+ # 3 3 C
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+
+ context "when that line was moved between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, update_line_commit) }
+ let(:new_diff_refs) { diff_refs(move_line_commit, move_second_file_line_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 2) }
+
+ # old diff:
+ # 1 + A
+ # 2 + BB
+ # 3 + C
+ #
+ # new diff:
+ # 1 1 BB
+ # 2 2 A
+ # 3 3 C
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+
+ context "when that line was changed between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
+ let(:new_diff_refs) { diff_refs(update_line_commit, update_second_file_line_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 2) }
+
+ # old diff:
+ # 1 + A
+ # 2 + B
+ # 3 + C
+ #
+ # new diff:
+ # 1 1 A
+ # 2 2 BB
+ # 3 3 C
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+
+ context "when that line was deleted between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(initial_commit, move_line_commit) }
+ let(:new_diff_refs) { diff_refs(delete_line_commit, delete_second_file_line_commit) }
+ let(:old_position) { position(new_path: file_name, new_line: 3) }
+
+ # old diff:
+ # 1 + BB
+ # 2 + A
+ # 3 + C
+ #
+ # new diff:
+ # 1 1 BB
+ # 2 2 A
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+ end
+ end
+ end
+ end
+
+ context "when the file was changed in the old diff" do
+ context "when the file is created in the new diff" do
+ context "when the position pointed at an added line in the old diff" do
+ context "when the file's content was unchanged between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
+ let(:new_diff_refs) { diff_refs(initial_commit, update_line_commit) }
+ let(:old_position) { position(old_path: file_name, new_path: file_name, new_line: 2) }
+
+ # old diff:
+ # 1 1 A
+ # 2 - B
+ # 2 + BB
+ # 3 3 C
+ #
+ # new diff:
+ # 1 + A
+ # 2 + BB
+ # 3 + C
+
+ it "returns the new position" do
+ expect_new_position(
+ new_path: old_position.new_path,
+ old_line: nil,
+ new_line: old_position.new_line
+ )
+ end
+ end
+
+ context "when the file's content was changed between the old and the new diff" do
+ context "when that line was unchanged between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(create_file_commit, move_line_commit) }
+ let(:new_diff_refs) { diff_refs(initial_commit, move_line_commit) }
+ let(:old_position) { position(old_path: file_name, new_path: file_name, new_line: 1) }
+
+ # old diff:
+ # 1 + BB
+ # 1 2 A
+ # 2 - B
+ # 3 3 C
+ #
+ # new diff:
+ # 1 + BB
+ # 2 + A
+
+ it "returns the new position" do
+ expect_new_position(
+ new_path: old_position.new_path,
+ old_line: nil,
+ new_line: old_position.new_line
+ )
+ end
+ end
+
+ context "when that line was moved between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
+ let(:new_diff_refs) { diff_refs(initial_commit, move_line_commit) }
+ let(:old_position) { position(old_path: file_name, new_path: file_name, new_line: 2) }
+
+ # old diff:
+ # 1 1 A
+ # 2 - B
+ # 2 + BB
+ # 3 3 C
+ #
+ # new diff:
+ # 1 + BB
+ # 2 + A
+ # 3 + C
+
+ it "returns the new position" do
+ expect_new_position(
+ new_path: old_position.new_path,
+ old_line: nil,
+ new_line: 1
+ )
+ end
+ end
+
+ context "when that line was changed or deleted between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(create_file_commit, move_line_commit) }
+ let(:new_diff_refs) { diff_refs(initial_commit, create_file_commit) }
+ let(:old_position) { position(old_path: file_name, new_path: file_name, new_line: 1) }
+
+ # old diff:
+ # 1 + BB
+ # 1 2 A
+ # 2 - B
+ # 3 3 C
+ #
+ # new diff:
+ # 1 + A
+ # 2 + B
+ # 3 + C
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+ end
+ end
+
+ context "when the position pointed at a deleted line in the old diff" do
+ let(:old_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
+ let(:new_diff_refs) { diff_refs(initial_commit, update_line_commit) }
+ let(:old_position) { position(old_path: file_name, new_path: file_name, old_line: 2) }
+
+ # old diff:
+ # 1 1 A
+ # 2 - B
+ # 2 + BB
+ # 3 3 C
+ #
+ # new diff:
+ # 1 + A
+ # 2 + BB
+ # 3 + C
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+
+ context "when the position pointed at an unchanged line in the old diff" do
+ context "when the file's content was unchanged between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
+ let(:new_diff_refs) { diff_refs(initial_commit, update_line_commit) }
+ let(:old_position) { position(old_path: file_name, new_path: file_name, old_line: 1, new_line: 1) }
+
+ # old diff:
+ # 1 1 A
+ # 2 - B
+ # 2 + BB
+ # 3 3 C
+ #
+ # new diff:
+ # 1 + A
+ # 2 + BB
+ # 3 + C
+
+ it "returns the new position" do
+ expect_new_position(
+ new_path: old_position.new_path,
+ old_line: nil,
+ new_line: old_position.new_line
+ )
+ end
+ end
+
+ context "when the file's content was changed between the old and the new diff" do
+ context "when that line was unchanged between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(create_file_commit, move_line_commit) }
+ let(:new_diff_refs) { diff_refs(initial_commit, move_line_commit) }
+ let(:old_position) { position(old_path: file_name, new_path: file_name, old_line: 1, new_line: 2) }
+
+ # old diff:
+ # 1 + BB
+ # 1 2 A
+ # 2 - B
+ # 3 3 C
+ #
+ # new diff:
+ # 1 + BB
+ # 2 + A
+
+ it "returns the new position" do
+ expect_new_position(
+ new_path: old_position.new_path,
+ old_line: nil,
+ new_line: old_position.new_line
+ )
+ end
+ end
+
+ context "when that line was moved between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(move_line_commit, delete_line_commit) }
+ let(:new_diff_refs) { diff_refs(initial_commit, update_line_commit) }
+ let(:old_position) { position(old_path: file_name, new_path: file_name, old_line: 2, new_line: 2) }
+
+ # old diff:
+ # 1 1 BB
+ # 2 2 A
+ # 3 - C
+ #
+ # new diff:
+ # 1 + A
+ # 2 + BB
+ # 3 + C
+
+ it "returns the new position" do
+ expect_new_position(
+ new_path: old_position.new_path,
+ old_line: nil,
+ new_line: 1
+ )
+ end
+ end
+
+ context "when that line was changed or deleted between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(create_file_commit, move_line_commit) }
+ let(:new_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
+ let(:old_position) { position(old_path: file_name, new_path: file_name, old_line: 3, new_line: 3) }
+
+ # old diff:
+ # 1 + BB
+ # 1 2 A
+ # 2 - B
+ # 3 3 C
+ #
+ # new diff:
+ # 1 + A
+ # 2 + B
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+ end
+ end
+ end
+
+ context "when the file is changed in the new diff" do
+ context "when the position pointed at an added line in the old diff" do
+ context "when the file's content was unchanged between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
+ let(:new_diff_refs) { diff_refs(create_file_commit, update_second_file_line_commit) }
+ let(:old_position) { position(old_path: file_name, new_path: file_name, new_line: 2) }
+
+ # old diff:
+ # 1 1 A
+ # 2 - B
+ # 2 + BB
+ # 3 3 C
+ #
+ # new diff:
+ # 1 1 A
+ # 2 - B
+ # 2 + BB
+ # 3 3 C
+
+ it "returns the new position" do
+ expect_new_position(
+ old_path: old_position.old_path,
+ new_path: old_position.new_path,
+ old_line: nil,
+ new_line: old_position.new_line
+ )
+ end
+ end
+
+ context "when the file's content was changed between the old and the new diff" do
+ context "when that line was unchanged between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(create_file_commit, move_line_commit) }
+ let(:new_diff_refs) { diff_refs(move_line_commit, delete_line_commit) }
+ let(:old_position) { position(old_path: file_name, new_path: file_name, new_line: 1) }
+
+ # old diff:
+ # 1 + BB
+ # 1 2 A
+ # 2 - B
+ # 3 3 C
+ #
+ # new diff:
+ # 1 1 BB
+ # 2 2 A
+ # 3 - C
+
+ it "returns the new position" do
+ expect_new_position(
+ old_path: old_position.old_path,
+ new_path: old_position.new_path,
+ old_line: 1,
+ new_line: 1
+ )
+ end
+ end
+
+ context "when that line was moved between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
+ let(:new_diff_refs) { diff_refs(update_line_commit, move_line_commit) }
+ let(:old_position) { position(old_path: file_name, new_path: file_name, new_line: 2) }
+
+ # old diff:
+ # 1 1 A
+ # 2 - B
+ # 2 + BB
+ # 3 3 C
+ #
+ # new diff:
+ # 1 - A
+ # 2 1 BB
+ # 2 + A
+ # 3 3 C
+
+ it "returns the new position" do
+ expect_new_position(
+ old_path: old_position.old_path,
+ new_path: old_position.new_path,
+ old_line: 2,
+ new_line: 1
+ )
+ end
+ end
+
+ context "when that line was changed or deleted between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(create_file_commit, move_line_commit) }
+ let(:new_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
+ let(:old_position) { position(old_path: file_name, new_path: file_name, new_line: 1) }
+
+ # old diff:
+ # 1 + BB
+ # 1 2 A
+ # 2 - B
+ # 3 3 C
+ #
+ # new diff:
+ # 1 1 A
+ # 2 - B
+ # 2 + BB
+ # 3 3 C
+
+ it "returns nil" do
+ expect(subject).to be_nil
+ end
+ end
+ end
+ end
+
+ context "when the position pointed at a deleted line in the old diff" do
+ context "when the file's content was unchanged between the old and the new diff" do
+ let(:old_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
+ let(:new_diff_refs) { diff_refs(create_file_commit, update_second_file_line_commit) }
+ let(:old_position) { position(old_path: file_name, new_path: file_name, old_line: 2) }
+
+ # old diff:
+ # 1 1 A
+ # 2 - B
+ # 2 + BB
+ # 3 3 C
+ #
+ # new diff:
+ # 1 1 A
+ # 2 - B
+ # 2 + BB
+ # 3 3 C
+
+ it "returns the new position" do
+ expect_new_position(
+ old_path: old_position.old_path,
+ new_path: old_position.new_path,
+ old_line: old_position.old_line,
+ new_line: nil
+ )
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ describe "typical use scenarios" do
+ let(:second_branch_name) { "#{branch_name}-2" }
+
+ def expect_positions(old_attrs, new_attrs)
+ old_positions = old_attrs.map do |old_attrs|
+ position(old_attrs)
+ end
+
+ new_positions = old_positions.map do |old_position|
+ position_tracer.trace(old_position)
+ end
+
+ new_positions.zip(new_attrs).each do |new_position, new_attrs|
+ expect_new_position(new_attrs, new_position)
+ end
+ end
+
+ let(:create_file_commit) do
+ initial_commit
+
+ create_file(
+ branch_name,
+ file_name,
+ <<-CONTENT.strip_heredoc
+ A
+ B
+ C
+ D
+ E
+ F
+ CONTENT
+ )
+ end
+
+ let(:second_create_file_commit) do
+ create_file_commit
+
+ create_branch(second_branch_name, branch_name)
+
+ update_file(
+ second_branch_name,
+ file_name,
+ <<-CONTENT.strip_heredoc
+ Z
+ Z
+ Z
+ A
+ B
+ C
+ D
+ E
+ F
+ CONTENT
+ )
+ end
+
+ let(:update_file_commit) do
+ second_create_file_commit
+
+ update_file(
+ branch_name,
+ file_name,
+ <<-CONTENT.strip_heredoc
+ A
+ C
+ DD
+ E
+ F
+ G
+ CONTENT
+ )
+ end
+
+ let(:update_file_again_commit) do
+ update_file_commit
+
+ update_file(
+ branch_name,
+ file_name,
+ <<-CONTENT.strip_heredoc
+ A
+ BB
+ C
+ D
+ E
+ FF
+ G
+ CONTENT
+ )
+ end
+
+ describe "simple push of new commit" do
+ let(:old_diff_refs) { diff_refs(create_file_commit, update_file_commit) }
+ let(:new_diff_refs) { diff_refs(create_file_commit, update_file_again_commit) }
+
+ # old diff:
+ # 1 1 A
+ # 2 - B
+ # 3 2 C
+ # 4 - D
+ # 3 + DD
+ # 5 4 E
+ # 6 5 F
+ # 6 + G
+ #
+ # new diff:
+ # 1 1 A
+ # 2 - B
+ # 2 + BB
+ # 3 3 C
+ # 4 4 D
+ # 5 5 E
+ # 6 - F
+ # 6 + FF
+ # 7 + G
+
+ it "returns the new positions" do
+ old_position_attrs = [
+ { old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 }, # A
+ { old_path: file_name, old_line: 2 }, # - B
+ { old_path: file_name, new_path: file_name, old_line: 3, new_line: 2 }, # C
+ { old_path: file_name, old_line: 4 }, # - D
+ { new_path: file_name, new_line: 3 }, # + DD
+ { old_path: file_name, new_path: file_name, old_line: 5, new_line: 4 }, # E
+ { old_path: file_name, new_path: file_name, old_line: 6, new_line: 5 }, # F
+ { new_path: file_name, new_line: 6 }, # + G
+ ]
+
+ new_position_attrs = [
+ { old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 },
+ { old_path: file_name, old_line: 2 },
+ { old_path: file_name, new_path: file_name, old_line: 3, new_line: 3 },
+ { old_path: file_name, old_line: 4, new_line: 4 },
+ nil,
+ { old_path: file_name, new_path: file_name, old_line: 5, new_line: 5 },
+ { old_path: file_name, old_line: 6 },
+ { new_path: file_name, new_line: 7 },
+ ]
+
+ expect_positions(old_position_attrs, new_position_attrs)
+ end
+ end
+
+ describe "force push to overwrite last commit" do
+ let(:second_create_file_commit) do
+ create_file_commit
+
+ create_branch(second_branch_name, branch_name)
+
+ update_file(
+ second_branch_name,
+ file_name,
+ <<-CONTENT.strip_heredoc
+ A
+ BB
+ C
+ D
+ E
+ FF
+ G
+ CONTENT
+ )
+ end
+
+ let(:old_diff_refs) { diff_refs(create_file_commit, update_file_commit) }
+ let(:new_diff_refs) { diff_refs(create_file_commit, second_create_file_commit) }
+
+ # old diff:
+ # 1 1 A
+ # 2 - B
+ # 3 2 C
+ # 4 - D
+ # 3 + DD
+ # 5 4 E
+ # 6 5 F
+ # 6 + G
+ #
+ # new diff:
+ # 1 1 A
+ # 2 - B
+ # 2 + BB
+ # 3 3 C
+ # 4 4 D
+ # 5 5 E
+ # 6 - F
+ # 6 + FF
+ # 7 + G
+
+ it "returns the new positions" do
+ old_position_attrs = [
+ { old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 }, # A
+ { old_path: file_name, old_line: 2 }, # - B
+ { old_path: file_name, new_path: file_name, old_line: 3, new_line: 2 }, # C
+ { old_path: file_name, old_line: 4 }, # - D
+ { new_path: file_name, new_line: 3 }, # + DD
+ { old_path: file_name, new_path: file_name, old_line: 5, new_line: 4 }, # E
+ { old_path: file_name, new_path: file_name, old_line: 6, new_line: 5 }, # F
+ { new_path: file_name, new_line: 6 }, # + G
+ ]
+
+ new_position_attrs = [
+ { old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 },
+ { old_path: file_name, old_line: 2 },
+ { old_path: file_name, new_path: file_name, old_line: 3, new_line: 3 },
+ { old_path: file_name, old_line: 4, new_line: 4 },
+ nil,
+ { old_path: file_name, new_path: file_name, old_line: 5, new_line: 5 },
+ { old_path: file_name, old_line: 6 },
+ { new_path: file_name, new_line: 7 },
+ ]
+
+ expect_positions(old_position_attrs, new_position_attrs)
+ end
+ end
+
+ describe "force push to delete last commit" do
+ let(:old_diff_refs) { diff_refs(create_file_commit, update_file_again_commit) }
+ let(:new_diff_refs) { diff_refs(create_file_commit, update_file_commit) }
+
+ # old diff:
+ # 1 1 A
+ # 2 - B
+ # 2 + BB
+ # 3 3 C
+ # 4 4 D
+ # 5 5 E
+ # 6 - F
+ # 6 + FF
+ # 7 + G
+ #
+ # new diff:
+ # 1 1 A
+ # 2 - B
+ # 3 2 C
+ # 4 - D
+ # 3 + DD
+ # 5 4 E
+ # 6 5 F
+ # 6 + G
+
+ it "returns the new positions" do
+ old_position_attrs = [
+ { old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 }, # A
+ { old_path: file_name, old_line: 2 }, # - B
+ { new_path: file_name, new_line: 2 }, # + BB
+ { old_path: file_name, new_path: file_name, old_line: 3, new_line: 3 }, # C
+ { old_path: file_name, new_path: file_name, old_line: 4, new_line: 4 }, # D
+ { old_path: file_name, new_path: file_name, old_line: 5, new_line: 5 }, # E
+ { old_path: file_name, old_line: 6 }, # - F
+ { new_path: file_name, new_line: 6 }, # + FF
+ { new_path: file_name, new_line: 7 }, # + G
+ ]
+
+ new_position_attrs = [
+ { old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 },
+ { old_path: file_name, old_line: 2 },
+ nil,
+ { old_path: file_name, new_path: file_name, old_line: 3, new_line: 2 },
+ { old_path: file_name, old_line: 4 },
+ { old_path: file_name, new_path: file_name, old_line: 5, new_line: 4 },
+ { old_path: file_name, new_path: file_name, old_line: 6, new_line: 5 },
+ nil,
+ { new_path: file_name, new_line: 6 },
+ ]
+
+ expect_positions(old_position_attrs, new_position_attrs)
+ end
+ end
+
+ describe "rebase on top of target branch" do
+ let(:second_update_file_commit) do
+ update_file_commit
+
+ update_file(
+ second_branch_name,
+ file_name,
+ <<-CONTENT.strip_heredoc
+ Z
+ Z
+ Z
+ A
+ C
+ DD
+ E
+ F
+ G
+ CONTENT
+ )
+ end
+
+ let(:update_file_again_commit) do
+ second_update_file_commit
+
+ update_file(
+ branch_name,
+ file_name,
+ <<-CONTENT.strip_heredoc
+ A
+ BB
+ C
+ D
+ E
+ FF
+ G
+ CONTENT
+ )
+ end
+
+ let(:overwrite_update_file_again_commit) do
+ update_file_again_commit
+
+ update_file(
+ second_branch_name,
+ file_name,
+ <<-CONTENT.strip_heredoc
+ Z
+ Z
+ Z
+ A
+ BB
+ C
+ D
+ E
+ FF
+ G
+ CONTENT
+ )
+ end
+
+ let(:old_diff_refs) { diff_refs(create_file_commit, update_file_again_commit) }
+ let(:new_diff_refs) { diff_refs(create_file_commit, overwrite_update_file_again_commit) }
+
+ # old diff:
+ # 1 1 A
+ # 2 - B
+ # 2 + BB
+ # 3 3 C
+ # 4 4 D
+ # 5 5 E
+ # 6 - F
+ # 6 + FF
+ # 7 + G
+ #
+ # new diff:
+ # 1 + Z
+ # 2 + Z
+ # 3 + Z
+ # 1 4 A
+ # 2 - B
+ # 5 + BB
+ # 3 6 C
+ # 4 7 D
+ # 5 8 E
+ # 6 - F
+ # 9 + FF
+ # 0 + G
+
+ it "returns the new positions" do
+ old_position_attrs = [
+ { old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 }, # A
+ { old_path: file_name, old_line: 2 }, # - B
+ { new_path: file_name, new_line: 2 }, # + BB
+ { old_path: file_name, new_path: file_name, old_line: 3, new_line: 3 }, # C
+ { old_path: file_name, new_path: file_name, old_line: 4, new_line: 4 }, # D
+ { old_path: file_name, new_path: file_name, old_line: 5, new_line: 5 }, # E
+ { old_path: file_name, old_line: 6 }, # - F
+ { new_path: file_name, new_line: 6 }, # + FF
+ { new_path: file_name, new_line: 7 }, # + G
+ ]
+
+ new_position_attrs = [
+ { old_path: file_name, new_path: file_name, old_line: 1, new_line: 4 }, # A
+ { old_path: file_name, old_line: 2 }, # - B
+ { new_path: file_name, new_line: 5 }, # + BB
+ { old_path: file_name, new_path: file_name, old_line: 3, new_line: 6 }, # C
+ { old_path: file_name, new_path: file_name, old_line: 4, new_line: 7 }, # D
+ { old_path: file_name, new_path: file_name, old_line: 5, new_line: 8 }, # E
+ { old_path: file_name, old_line: 6 }, # - F
+ { new_path: file_name, new_line: 9 }, # + FF
+ { new_path: file_name, new_line: 10 }, # + G
+ ]
+
+ expect_positions(old_position_attrs, new_position_attrs)
+ end
+ end
+
+ describe "merge of target branch" do
+ let(:merge_commit) do
+ update_file_again_commit
+
+ committer = repository.user_to_committer(current_user)
+
+ options = {
+ message: "Merge branches",
+ author: committer,
+ committer: committer
+ }
+
+ repository.merge(current_user, second_create_file_commit.sha, branch_name, options)
+ project.commit(branch_name)
+ end
+
+ let(:old_diff_refs) { diff_refs(create_file_commit, update_file_again_commit) }
+ let(:new_diff_refs) { diff_refs(create_file_commit, merge_commit) }
+
+ # old diff:
+ # 1 1 A
+ # 2 - B
+ # 2 + BB
+ # 3 3 C
+ # 4 4 D
+ # 5 5 E
+ # 6 - F
+ # 6 + FF
+ # 7 + G
+ #
+ # new diff:
+ # 1 + Z
+ # 2 + Z
+ # 3 + Z
+ # 1 4 A
+ # 2 - B
+ # 5 + BB
+ # 3 6 C
+ # 4 7 D
+ # 5 8 E
+ # 6 - F
+ # 9 + FF
+ # 0 + G
+
+ it "returns the new positions" do
+ old_position_attrs = [
+ { old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 }, # A
+ { old_path: file_name, old_line: 2 }, # - B
+ { new_path: file_name, new_line: 2 }, # + BB
+ { old_path: file_name, new_path: file_name, old_line: 3, new_line: 3 }, # C
+ { old_path: file_name, new_path: file_name, old_line: 4, new_line: 4 }, # D
+ { old_path: file_name, new_path: file_name, old_line: 5, new_line: 5 }, # E
+ { old_path: file_name, old_line: 6 }, # - F
+ { new_path: file_name, new_line: 6 }, # + FF
+ { new_path: file_name, new_line: 7 }, # + G
+ ]
+
+ new_position_attrs = [
+ { old_path: file_name, new_path: file_name, old_line: 1, new_line: 4 }, # A
+ { old_path: file_name, old_line: 2 }, # - B
+ { new_path: file_name, new_line: 5 }, # + BB
+ { old_path: file_name, new_path: file_name, old_line: 3, new_line: 6 }, # C
+ { old_path: file_name, new_path: file_name, old_line: 4, new_line: 7 }, # D
+ { old_path: file_name, new_path: file_name, old_line: 5, new_line: 8 }, # E
+ { old_path: file_name, old_line: 6 }, # - F
+ { new_path: file_name, new_line: 9 }, # + FF
+ { new_path: file_name, new_line: 10 }, # + G
+ ]
+
+ expect_positions(old_position_attrs, new_position_attrs)
+ end
+ end
+
+ describe "changing target branch" do
+ let(:old_diff_refs) { diff_refs(create_file_commit, update_file_again_commit) }
+ let(:new_diff_refs) { diff_refs(update_file_commit, update_file_again_commit) }
+
+ # old diff:
+ # 1 1 A
+ # 2 - B
+ # 2 + BB
+ # 3 3 C
+ # 4 4 D
+ # 5 5 E
+ # 6 - F
+ # 6 + FF
+ # 7 + G
+ #
+ # new diff:
+ # 1 1 A
+ # 2 + BB
+ # 2 3 C
+ # 3 - DD
+ # 4 + D
+ # 4 5 E
+ # 5 - F
+ # 6 + FF
+ # 7 G
+
+ it "returns the new positions" do
+ old_position_attrs = [
+ { old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 }, # A
+ { old_path: file_name, old_line: 2 }, # - B
+ { new_path: file_name, new_line: 2 }, # + BB
+ { old_path: file_name, new_path: file_name, old_line: 3, new_line: 3 }, # C
+ { old_path: file_name, new_path: file_name, old_line: 4, new_line: 4 }, # D
+ { old_path: file_name, new_path: file_name, old_line: 5, new_line: 5 }, # E
+ { old_path: file_name, old_line: 6 }, # - F
+ { new_path: file_name, new_line: 6 }, # + FF
+ { new_path: file_name, new_line: 7 }, # + G
+ ]
+
+ new_position_attrs = [
+ { old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 },
+ nil,
+ { new_path: file_name, new_line: 2 },
+ { old_path: file_name, new_path: file_name, old_line: 2, new_line: 3 },
+ { new_path: file_name, new_line: 4 },
+ { old_path: file_name, new_path: file_name, old_line: 4, new_line: 5 },
+ { old_path: file_name, old_line: 5 },
+ { new_path: file_name, new_line: 6 },
+ { new_path: file_name, new_line: 7 },
+ ]
+
+ expect_positions(old_position_attrs, new_position_attrs)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/git/hook_spec.rb b/spec/lib/gitlab/git/hook_spec.rb
new file mode 100644
index 00000000000..a15aa173fbd
--- /dev/null
+++ b/spec/lib/gitlab/git/hook_spec.rb
@@ -0,0 +1,70 @@
+require 'spec_helper'
+require 'fileutils'
+
+describe Gitlab::Git::Hook, lib: true do
+ describe "#trigger" do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ def create_hook(name)
+ FileUtils.mkdir_p(File.join(project.repository.path, 'hooks'))
+ File.open(File.join(project.repository.path, 'hooks', name), 'w', 0755) do |f|
+ f.write('exit 0')
+ end
+ end
+
+ def create_failing_hook(name)
+ FileUtils.mkdir_p(File.join(project.repository.path, 'hooks'))
+ File.open(File.join(project.repository.path, 'hooks', name), 'w', 0755) do |f|
+ f.write(<<-HOOK)
+ echo 'regular message from the hook'
+ echo 'error message from the hook' 1>&2
+ exit 1
+ HOOK
+ end
+ end
+
+ ['pre-receive', 'post-receive', 'update'].each do |hook_name|
+
+ context "when triggering a #{hook_name} hook" do
+ context "when the hook is successful" do
+ it "returns success with no errors" do
+ create_hook(hook_name)
+ hook = Gitlab::Git::Hook.new(hook_name, project.repository.path)
+ blank = Gitlab::Git::BLANK_SHA
+ ref = Gitlab::Git::BRANCH_REF_PREFIX + 'new_branch'
+
+ status, errors = hook.trigger(Gitlab::GlId.gl_id(user), blank, blank, ref)
+ expect(status).to be true
+ expect(errors).to be_blank
+ end
+ end
+
+ context "when the hook is unsuccessful" do
+ it "returns failure with errors" do
+ create_failing_hook(hook_name)
+ hook = Gitlab::Git::Hook.new(hook_name, project.repository.path)
+ blank = Gitlab::Git::BLANK_SHA
+ ref = Gitlab::Git::BRANCH_REF_PREFIX + 'new_branch'
+
+ status, errors = hook.trigger(Gitlab::GlId.gl_id(user), blank, blank, ref)
+ expect(status).to be false
+ expect(errors).to eq("error message from the hook\n")
+ end
+ end
+ end
+ end
+
+ context "when the hook doesn't exist" do
+ it "returns success with no errors" do
+ hook = Gitlab::Git::Hook.new('unknown_hook', project.repository.path)
+ blank = Gitlab::Git::BLANK_SHA
+ ref = Gitlab::Git::BRANCH_REF_PREFIX + 'new_branch'
+
+ status, errors = hook.trigger(Gitlab::GlId.gl_id(user), blank, blank, ref)
+ expect(status).to be true
+ expect(errors).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb
index 9b7986fa12d..c79ba11f782 100644
--- a/spec/lib/gitlab/git_access_spec.rb
+++ b/spec/lib/gitlab/git_access_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Gitlab::GitAccess, lib: true do
- let(:access) { Gitlab::GitAccess.new(actor, project) }
+ let(:access) { Gitlab::GitAccess.new(actor, project, 'web') }
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:actor) { user }
@@ -67,6 +67,43 @@ describe Gitlab::GitAccess, lib: true do
end
end
+ describe '#check with single protocols allowed' do
+ def disable_protocol(protocol)
+ settings = ::ApplicationSetting.create_from_defaults
+ settings.update_attribute(:enabled_git_access_protocol, protocol)
+ end
+
+ context 'ssh disabled' do
+ before do
+ disable_protocol('ssh')
+ @acc = Gitlab::GitAccess.new(actor, project, 'ssh')
+ end
+
+ it 'blocks ssh git push' do
+ expect(@acc.check('git-receive-pack').allowed?).to be_falsey
+ end
+
+ it 'blocks ssh git pull' do
+ expect(@acc.check('git-upload-pack').allowed?).to be_falsey
+ end
+ end
+
+ context 'http disabled' do
+ before do
+ disable_protocol('http')
+ @acc = Gitlab::GitAccess.new(actor, project, 'http')
+ end
+
+ it 'blocks http push' do
+ expect(@acc.check('git-receive-pack').allowed?).to be_falsey
+ end
+
+ it 'blocks http git pull' do
+ expect(@acc.check('git-upload-pack').allowed?).to be_falsey
+ end
+ end
+ end
+
describe 'download_access_check' do
describe 'master permissions' do
before { project.team << [user, :master] }
diff --git a/spec/lib/gitlab/git_access_wiki_spec.rb b/spec/lib/gitlab/git_access_wiki_spec.rb
index 77ecfce6f17..4244b807d41 100644
--- a/spec/lib/gitlab/git_access_wiki_spec.rb
+++ b/spec/lib/gitlab/git_access_wiki_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Gitlab::GitAccessWiki, lib: true do
- let(:access) { Gitlab::GitAccessWiki.new(user, project) }
+ let(:access) { Gitlab::GitAccessWiki.new(user, project, 'web') }
let(:project) { create(:project) }
let(:user) { create(:user) }
diff --git a/spec/lib/gitlab/github_import/branch_formatter_spec.rb b/spec/lib/gitlab/github_import/branch_formatter_spec.rb
index 3cb634ba010..fc9d5204148 100644
--- a/spec/lib/gitlab/github_import/branch_formatter_spec.rb
+++ b/spec/lib/gitlab/github_import/branch_formatter_spec.rb
@@ -2,17 +2,18 @@ require 'spec_helper'
describe Gitlab::GithubImport::BranchFormatter, lib: true do
let(:project) { create(:project) }
+ let(:commit) { create(:commit, project: project) }
let(:repo) { double }
let(:raw) do
{
ref: 'feature',
repo: repo,
- sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b'
+ sha: commit.id
}
end
describe '#exists?' do
- it 'returns true when branch exists' do
+ it 'returns true when both branch, and commit exists' do
branch = described_class.new(project, double(raw))
expect(branch.exists?).to eq true
@@ -23,6 +24,12 @@ describe Gitlab::GithubImport::BranchFormatter, lib: true do
expect(branch.exists?).to eq false
end
+
+ it 'returns false when commit does not exist' do
+ branch = described_class.new(project, double(raw.merge(sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b')))
+
+ expect(branch.exists?).to eq false
+ end
end
describe '#name' do
@@ -33,7 +40,7 @@ describe Gitlab::GithubImport::BranchFormatter, lib: true do
end
it 'returns formatted ref when branch does not exist' do
- branch = described_class.new(project, double(raw.merge(ref: 'removed-branch')))
+ branch = described_class.new(project, double(raw.merge(ref: 'removed-branch', sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b')))
expect(branch.name).to eq 'removed-branch-2e5d3239'
end
@@ -51,18 +58,18 @@ describe Gitlab::GithubImport::BranchFormatter, lib: true do
it 'returns raw sha' do
branch = described_class.new(project, double(raw))
- expect(branch.sha).to eq '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b'
+ expect(branch.sha).to eq commit.id
end
end
describe '#valid?' do
- it 'returns true when repository exists' do
+ it 'returns true when raw repo is present' do
branch = described_class.new(project, double(raw))
expect(branch.valid?).to eq true
end
- it 'returns false when repository does not exist' do
+ it 'returns false when raw repo is blank' do
branch = described_class.new(project, double(raw.merge(repo: nil)))
expect(branch.valid?).to eq false
diff --git a/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb b/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb
index 120f59e6e71..79931ecd134 100644
--- a/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb
+++ b/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb
@@ -2,11 +2,13 @@ require 'spec_helper'
describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
let(:project) { create(:project) }
+ let(:source_sha) { create(:commit, project: project).id }
+ let(:target_sha) { create(:commit, project: project, git_commit: RepoHelpers.another_sample_commit).id }
let(:repository) { double(id: 1, fork: false) }
let(:source_repo) { repository }
- let(:source_branch) { double(ref: 'feature', repo: source_repo, sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b') }
+ let(:source_branch) { double(ref: 'feature', repo: source_repo, sha: source_sha) }
let(:target_repo) { repository }
- let(:target_branch) { double(ref: 'master', repo: target_repo, sha: '8ffb3c15a5475e59ae909384297fede4badcb4c7') }
+ let(:target_branch) { double(ref: 'master', repo: target_repo, sha: target_sha) }
let(:octocat) { double(id: 123456, login: 'octocat') }
let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') }
let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') }
@@ -41,10 +43,10 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
description: "*Created by: octocat*\n\nPlease pull these awesome changes",
source_project: project,
source_branch: 'feature',
- head_source_sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b',
+ source_branch_sha: source_sha,
target_project: project,
target_branch: 'master',
- base_target_sha: '8ffb3c15a5475e59ae909384297fede4badcb4c7',
+ target_branch_sha: target_sha,
state: 'opened',
milestone: nil,
author_id: project.creator_id,
@@ -68,10 +70,10 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
description: "*Created by: octocat*\n\nPlease pull these awesome changes",
source_project: project,
source_branch: 'feature',
- head_source_sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b',
+ source_branch_sha: source_sha,
target_project: project,
target_branch: 'master',
- base_target_sha: '8ffb3c15a5475e59ae909384297fede4badcb4c7',
+ target_branch_sha: target_sha,
state: 'closed',
milestone: nil,
author_id: project.creator_id,
@@ -95,10 +97,10 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
description: "*Created by: octocat*\n\nPlease pull these awesome changes",
source_project: project,
source_branch: 'feature',
- head_source_sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b',
+ source_branch_sha: source_sha,
target_project: project,
target_branch: 'master',
- base_target_sha: '8ffb3c15a5475e59ae909384297fede4badcb4c7',
+ target_branch_sha: target_sha,
state: 'merged',
milestone: nil,
author_id: project.creator_id,
diff --git a/spec/lib/gitlab/graphs/commits_spec.rb b/spec/lib/gitlab/graphs/commits_spec.rb
new file mode 100644
index 00000000000..f5c064303ad
--- /dev/null
+++ b/spec/lib/gitlab/graphs/commits_spec.rb
@@ -0,0 +1,39 @@
+require 'spec_helper'
+
+describe Gitlab::Graphs::Commits, lib: true do
+ let!(:project) { create(:project, :public, :empty_repo) }
+
+ let!(:commit1) { create(:commit, git_commit: RepoHelpers.sample_commit, project: project, committed_date: Time.now) }
+ let!(:commit1_yesterday) { create(:commit, git_commit: RepoHelpers.sample_commit, project: project, committed_date: 1.day.ago)}
+
+ let!(:commit2) { create(:commit, git_commit: RepoHelpers.another_sample_commit, project: project, committed_date: Time.now) }
+
+ describe '#commit_per_day' do
+ context 'when range is only commits from today' do
+ subject { described_class.new([commit2, commit1]).commit_per_day }
+ it { is_expected.to eq 2 }
+ end
+ end
+
+ context 'when range is only commits from today' do
+ subject { described_class.new([commit2, commit1]) }
+ describe '#commit_per_day' do
+ it { expect(subject.commit_per_day).to eq 2 }
+ end
+
+ describe '#duration' do
+ it { expect(subject.duration).to eq 0 }
+ end
+ end
+
+ context 'with commits from yesterday and today' do
+ subject { described_class.new([commit2, commit1_yesterday]) }
+ describe '#commit_per_day' do
+ it { expect(subject.commit_per_day).to eq 1 }
+ end
+
+ describe '#duration' do
+ it { expect(subject.duration).to eq 1 }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json
index 0b30e8c9b04..7286b0c39c0 100644
--- a/spec/lib/gitlab/import_export/project.json
+++ b/spec/lib/gitlab/import_export/project.json
@@ -4208,7 +4208,18 @@
"name": "User 4"
},
"events": [
-
+ {
+ "id": 529,
+ "target_type": "Note",
+ "target_id": 2521,
+ "title": "test levels",
+ "data": null,
+ "project_id": 4,
+ "created_at": "2016-07-07T14:35:12.128Z",
+ "updated_at": "2016-07-07T14:35:12.128Z",
+ "action": 6,
+ "author_id": 1
+ }
]
},
{
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 a72aaa44e82..05ffec8ea0a 100644
--- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
@@ -24,11 +24,27 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do
expect(Ci::Pipeline.first.notes).not_to be_empty
end
- it 'restores the correct event' do
+ it 'restores the correct event with symbolised data' do
restored_project_json
expect(Event.where.not(data: nil).first.data[:ref]).not_to be_empty
end
+
+ context 'event at forth level of the tree' do
+ let(:event) { Event.where(title: 'test levels').first }
+
+ before do
+ restored_project_json
+ end
+
+ it 'restores the event' do
+ expect(event).not_to be_nil
+ end
+
+ it 'event belongs to note, belongs to merge request, belongs to a project' do
+ expect(event.note.noteable.project).not_to be_nil
+ end
+ end
end
end
end
diff --git a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
index a75eaa4d51f..1424de9e60b 100644
--- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
@@ -125,7 +125,7 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do
ci_pipeline = create(:ci_pipeline,
project: project,
- sha: merge_request.last_commit.id,
+ sha: merge_request.diff_head_sha,
ref: merge_request.source_branch,
statuses: [commit_status])
diff --git a/spec/lib/gitlab/metrics/subscribers/rails_cache_spec.rb b/spec/lib/gitlab/metrics/subscribers/rails_cache_spec.rb
index d824dc54438..d986c6fac43 100644
--- a/spec/lib/gitlab/metrics/subscribers/rails_cache_spec.rb
+++ b/spec/lib/gitlab/metrics/subscribers/rails_cache_spec.rb
@@ -13,6 +13,61 @@ describe Gitlab::Metrics::Subscribers::RailsCache do
subscriber.cache_read(event)
end
+
+ context 'with a transaction' do
+ before do
+ allow(subscriber).to receive(:current_transaction).
+ and_return(transaction)
+ end
+
+ context 'with hit event' do
+ let(:event) { double(:event, duration: 15.2, payload: { hit: true }) }
+
+ it 'increments the cache_read_hit count' do
+ expect(transaction).to receive(:increment).
+ with(:cache_read_hit_count, 1)
+ expect(transaction).to receive(:increment).
+ with(any_args).at_least(1) # Other calls
+
+ subscriber.cache_read(event)
+ end
+
+ context 'when super operation is fetch' do
+ let(:event) { double(:event, duration: 15.2, payload: { hit: true, super_operation: :fetch }) }
+
+ it 'does not increment cache read miss' do
+ expect(transaction).not_to receive(:increment).
+ with(:cache_read_hit_count, 1)
+
+ subscriber.cache_read(event)
+ end
+ end
+ end
+
+ context 'with miss event' do
+ let(:event) { double(:event, duration: 15.2, payload: { hit: false }) }
+
+ it 'increments the cache_read_miss count' do
+ expect(transaction).to receive(:increment).
+ with(:cache_read_miss_count, 1)
+ expect(transaction).to receive(:increment).
+ with(any_args).at_least(1) # Other calls
+
+ subscriber.cache_read(event)
+ end
+
+ context 'when super operation is fetch' do
+ let(:event) { double(:event, duration: 15.2, payload: { hit: false, super_operation: :fetch }) }
+
+ it 'does not increment cache read miss' do
+ expect(transaction).not_to receive(:increment).
+ with(:cache_read_miss_count, 1)
+
+ subscriber.cache_read(event)
+ end
+ end
+ end
+ end
end
describe '#cache_write' do
@@ -42,6 +97,54 @@ describe Gitlab::Metrics::Subscribers::RailsCache do
end
end
+ describe '#cache_fetch_hit' do
+ context 'without a transaction' do
+ it 'returns' do
+ expect(transaction).not_to receive(:increment)
+
+ subscriber.cache_fetch_hit(event)
+ end
+ end
+
+ context 'with a transaction' do
+ before do
+ allow(subscriber).to receive(:current_transaction).
+ and_return(transaction)
+ end
+
+ it 'increments the cache_read_hit count' do
+ expect(transaction).to receive(:increment).
+ with(:cache_read_hit_count, 1)
+
+ subscriber.cache_fetch_hit(event)
+ end
+ end
+ end
+
+ describe '#cache_generate' do
+ context 'without a transaction' do
+ it 'returns' do
+ expect(transaction).not_to receive(:increment)
+
+ subscriber.cache_generate(event)
+ end
+ end
+
+ context 'with a transaction' do
+ before do
+ allow(subscriber).to receive(:current_transaction).
+ and_return(transaction)
+ end
+
+ it 'increments the cache_fetch_miss count' do
+ expect(transaction).to receive(:increment).
+ with(:cache_read_miss_count, 1)
+
+ subscriber.cache_generate(event)
+ end
+ end
+ end
+
describe '#increment' do
context 'without a transaction' do
it 'returns' do
diff --git a/spec/lib/gitlab/note_data_builder_spec.rb b/spec/lib/gitlab/note_data_builder_spec.rb
index e848d88182f..3d6bcdfd873 100644
--- a/spec/lib/gitlab/note_data_builder_spec.rb
+++ b/spec/lib/gitlab/note_data_builder_spec.rb
@@ -27,7 +27,7 @@ describe 'Gitlab::NoteDataBuilder', lib: true do
end
describe 'When asking for a note on commit diff' do
- let(:note) { create(:note_on_commit_diff, project: project) }
+ let(:note) { create(:diff_note_on_commit, project: project) }
it 'returns the note and commit-specific data' do
expect(data).to have_key(:commit)
@@ -90,7 +90,7 @@ describe 'Gitlab::NoteDataBuilder', lib: true do
end
let(:note) do
- create(:note_on_merge_request_diff, noteable: merge_request,
+ create(:diff_note_on_merge_request, noteable: merge_request,
project: project)
end
diff --git a/spec/lib/gitlab/url_builder_spec.rb b/spec/lib/gitlab/url_builder_spec.rb
index bf11472407a..a826b24419a 100644
--- a/spec/lib/gitlab/url_builder_spec.rb
+++ b/spec/lib/gitlab/url_builder_spec.rb
@@ -43,9 +43,9 @@ describe Gitlab::UrlBuilder, lib: true do
end
end
- context 'on a CommitDiff' do
+ context 'on a Commit Diff' do
it 'returns a proper URL' do
- note = build_stubbed(:note_on_commit_diff)
+ note = build_stubbed(:diff_note_on_commit)
url = described_class.build(note)
@@ -75,10 +75,10 @@ describe Gitlab::UrlBuilder, lib: true do
end
end
- context 'on a MergeRequestDiff' do
+ context 'on a MergeRequest Diff' do
it 'returns a proper URL' do
merge_request = create(:merge_request, iid: 42)
- note = build_stubbed(:note_on_merge_request_diff, noteable: merge_request)
+ note = build_stubbed(:diff_note_on_merge_request, noteable: merge_request)
url = described_class.build(note)
diff --git a/spec/lib/gitlab/url_sanitizer_spec.rb b/spec/lib/gitlab/url_sanitizer_spec.rb
index 59024d3290b..2cb74629da8 100644
--- a/spec/lib/gitlab/url_sanitizer_spec.rb
+++ b/spec/lib/gitlab/url_sanitizer_spec.rb
@@ -45,6 +45,12 @@ describe Gitlab::UrlSanitizer, lib: true do
expect(filtered_content).to include("user@server:project.git")
end
+
+ it 'returns an empty string for invalid URLs' do
+ filtered_content = sanitize_url('ssh://')
+
+ expect(filtered_content).to include("repository '' not found")
+ end
end
describe '#sanitized_url' do
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index aa382f930d7..0a9b10bebea 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -948,7 +948,7 @@ describe Notify do
let(:commits) { Commit.decorate(compare.commits, nil) }
let(:diff_path) { namespace_project_compare_path(project.namespace, project, from: Commit.new(compare.base, project), to: Commit.new(compare.head, project)) }
let(:send_from_committer_email) { false }
- let(:diff_refs) { [project.merge_base_commit(sample_image_commit.id, sample_commit.id), project.commit(sample_commit.id)] }
+ let(:diff_refs) { Gitlab::Diff::DiffRefs.new(base_sha: project.merge_base_commit(sample_image_commit.id, sample_commit.id).id, head_sha: sample_commit.id) }
subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare, reverse_compare: false, diff_refs: diff_refs, send_from_committer_email: send_from_committer_email) }
@@ -1049,7 +1049,7 @@ describe Notify do
let(:compare) { Gitlab::Git::Compare.new(project.repository.raw_repository, sample_commit.parent_id, sample_commit.id) }
let(:commits) { Commit.decorate(compare.commits, nil) }
let(:diff_path) { namespace_project_commit_path(project.namespace, project, commits.first) }
- let(:diff_refs) { [project.merge_base_commit(sample_commit.parent_id, sample_commit.id), project.commit(sample_commit.id)] }
+ let(:diff_refs) { Gitlab::Diff::DiffRefs.new(base_sha: project.merge_base_commit(sample_image_commit.id, sample_commit.id).id, head_sha: sample_commit.id) }
subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare, diff_refs: diff_refs) }
diff --git a/spec/models/diff_note_spec.rb b/spec/models/diff_note_spec.rb
new file mode 100644
index 00000000000..af8e890ca95
--- /dev/null
+++ b/spec/models/diff_note_spec.rb
@@ -0,0 +1,191 @@
+require 'spec_helper'
+
+describe DiffNote, models: true do
+ include RepoHelpers
+
+ let(:project) { create(:project) }
+ let(:merge_request) { create(:merge_request, source_project: project) }
+ let(:commit) { project.commit(sample_commit.id) }
+
+ let(:path) { "files/ruby/popen.rb" }
+
+ let!(:position) do
+ Gitlab::Diff::Position.new(
+ old_path: path,
+ new_path: path,
+ old_line: nil,
+ new_line: 14,
+ diff_refs: merge_request.diff_refs
+ )
+ end
+
+ let!(:new_position) do
+ Gitlab::Diff::Position.new(
+ old_path: path,
+ new_path: path,
+ old_line: 16,
+ new_line: 22,
+ diff_refs: merge_request.diff_refs
+ )
+ end
+
+ subject { create(:diff_note_on_merge_request, project: project, position: position, noteable: merge_request) }
+
+ describe "#position=" do
+ context "when provided a string" do
+ it "sets the position" do
+ subject.position = new_position.to_json
+
+ expect(subject.position).to eq(new_position)
+ end
+ end
+
+ context "when provided a hash" do
+ it "sets the position" do
+ subject.position = new_position.to_h
+
+ expect(subject.position).to eq(new_position)
+ end
+ end
+
+ context "when provided a position object" do
+ it "sets the position" do
+ subject.position = new_position
+
+ expect(subject.position).to eq(new_position)
+ end
+ end
+ end
+
+ describe "#diff_file" do
+ it "returns the correct diff file" do
+ diff_file = subject.diff_file
+
+ expect(diff_file.old_path).to eq(position.old_path)
+ expect(diff_file.new_path).to eq(position.new_path)
+ expect(diff_file.diff_refs).to eq(position.diff_refs)
+ end
+ end
+
+ describe "#diff_line" do
+ it "returns the correct diff line" do
+ diff_line = subject.diff_line
+
+ expect(diff_line.added?).to be true
+ expect(diff_line.new_line).to eq(position.new_line)
+ expect(diff_line.text).to eq("+ vars = {")
+ end
+ end
+
+ describe "#line_code" do
+ it "returns the correct line code" do
+ line_code = Gitlab::Diff::LineCode.generate(position.file_path, position.new_line, 15)
+
+ expect(subject.line_code).to eq(line_code)
+ end
+ end
+
+ describe "#for_line?" do
+ context "when provided the correct diff line" do
+ it "returns true" do
+ expect(subject.for_line?(subject.diff_line)).to be true
+ end
+ end
+
+ context "when provided a different diff line" do
+ it "returns false" do
+ some_line = subject.diff_file.diff_lines.first
+
+ expect(subject.for_line?(some_line)).to be false
+ end
+ end
+ end
+
+ describe "#active?" do
+ context "when noteable is a commit" do
+ subject { create(:diff_note_on_commit, project: project, position: position) }
+
+ it "returns true" do
+ expect(subject.active?).to be true
+ end
+ end
+
+ context "when noteable is a merge request" do
+ context "when the merge request's diff refs match that of the diff note" do
+ it "returns true" do
+ expect(subject.active?).to be true
+ end
+ end
+
+ context "when the merge request's diff refs don't match that of the diff note" do
+ before do
+ allow(subject.noteable).to receive(:diff_refs).and_return(commit.diff_refs)
+ end
+
+ it "returns false" do
+ expect(subject.active?).to be false
+ end
+ end
+ end
+ end
+
+ describe "creation" do
+ describe "updating of position" do
+ context "when noteable is a commit" do
+ let(:diff_note) { create(:diff_note_on_commit, project: project, position: position) }
+
+ it "doesn't use the DiffPositionUpdateService" do
+ expect(Notes::DiffPositionUpdateService).not_to receive(:new)
+
+ diff_note
+ end
+
+ it "doesn't update the position" do
+ diff_note
+
+ expect(diff_note.original_position).to eq(position)
+ expect(diff_note.position).to eq(position)
+ end
+ end
+
+ context "when noteable is a merge request" do
+ let(:diff_note) { create(:diff_note_on_merge_request, project: project, position: position, noteable: merge_request) }
+
+ context "when the note is active" do
+ it "doesn't use the DiffPositionUpdateService" do
+ expect(Notes::DiffPositionUpdateService).not_to receive(:new)
+
+ diff_note
+ end
+
+ it "doesn't update the position" do
+ diff_note
+
+ expect(diff_note.original_position).to eq(position)
+ expect(diff_note.position).to eq(position)
+ end
+ end
+
+ context "when the note is outdated" do
+ before do
+ allow(merge_request).to receive(:diff_refs).and_return(commit.diff_refs)
+ end
+
+ it "uses the DiffPositionUpdateService" do
+ service = instance_double("Notes::DiffPositionUpdateService")
+ expect(Notes::DiffPositionUpdateService).to receive(:new).with(
+ project,
+ nil,
+ old_diff_refs: position.diff_refs,
+ new_diff_refs: commit.diff_refs,
+ paths: [path]
+ ).and_return(service)
+ expect(service).to receive(:execute)
+
+ diff_note
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index 166a1dc4ddb..b5d0d79e14e 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -46,6 +46,22 @@ describe Event, models: true do
it { expect(@event.author).to eq(@user) }
end
+ describe '#note?' do
+ subject { Event.new(project: target.project, target: target) }
+
+ context 'issue note event' do
+ let(:target) { create(:note_on_issue) }
+
+ it { is_expected.to be_note }
+ end
+
+ context 'merge request diff note event' do
+ let(:target) { create(:legacy_diff_note_on_merge_request) }
+
+ it { is_expected.to be_note }
+ end
+ end
+
describe '#visible_to_user?' do
let(:project) { create(:empty_project, :public) }
let(:non_member) { create(:user) }
@@ -89,7 +105,7 @@ describe Event, models: true do
end
end
- context 'note event' do
+ context 'issue note event' do
context 'on non confidential issues' do
let(:target) { note_on_issue }
@@ -112,6 +128,20 @@ describe Event, models: true do
it { expect(event.visible_to_user?(admin)).to eq true }
end
end
+
+ context 'merge request diff note event' do
+ let(:project) { create(:project, :public) }
+ let(:merge_request) { create(:merge_request, source_project: project, author: author, assignee: assignee) }
+ let(:note_on_merge_request) { create(:legacy_diff_note_on_merge_request, noteable: merge_request, project: project) }
+ let(:target) { note_on_merge_request }
+
+ it { expect(event.visible_to_user?(non_member)).to eq true }
+ it { expect(event.visible_to_user?(author)).to eq true }
+ it { expect(event.visible_to_user?(assignee)).to eq true }
+ it { expect(event.visible_to_user?(member)).to eq true }
+ it { expect(event.visible_to_user?(guest)).to eq true }
+ it { expect(event.visible_to_user?(admin)).to eq true }
+ end
end
describe '.limit_recent' do
diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb
index dad2628651b..f37f44a608e 100644
--- a/spec/models/label_spec.rb
+++ b/spec/models/label_spec.rb
@@ -32,21 +32,20 @@ describe Label, models: true do
it 'should validate title' do
expect(label).not_to allow_value('G,ITLAB').for(:title)
- expect(label).not_to allow_value('G?ITLAB').for(:title)
- expect(label).not_to allow_value('G&ITLAB').for(:title)
expect(label).not_to allow_value('').for(:title)
expect(label).to allow_value('GITLAB').for(:title)
expect(label).to allow_value('gitlab').for(:title)
+ expect(label).to allow_value('G?ITLAB').for(:title)
+ expect(label).to allow_value('G&ITLAB').for(:title)
expect(label).to allow_value("customer's request").for(:title)
end
end
- describe "#title" do
- let(:label) { create(:label, title: "<b>test</b>") }
-
- it "sanitizes title" do
- expect(label.title).to eq("test")
+ describe '#title' do
+ it 'sanitizes title' do
+ label = described_class.new(title: '<b>foo & bar?</b>')
+ expect(label.title).to eq('foo & bar?')
end
end
diff --git a/spec/models/legacy_diff_note_spec.rb b/spec/models/legacy_diff_note_spec.rb
index b2d06853886..d64d89edbd3 100644
--- a/spec/models/legacy_diff_note_spec.rb
+++ b/spec/models/legacy_diff_note_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe LegacyDiffNote, models: true do
describe "Commit diff line notes" do
- let!(:note) { create(:note_on_commit_diff, note: "+1 from me") }
+ let!(:note) { create(:legacy_diff_note_on_commit, note: "+1 from me") }
let!(:commit) { note.noteable }
it "should save a valid note" do
@@ -17,7 +17,7 @@ describe LegacyDiffNote, models: true do
describe '#active?' do
it 'is always true when the note has no associated diff' do
- note = build(:note_on_merge_request_diff)
+ note = build(:legacy_diff_note_on_merge_request)
expect(note).to receive(:diff).and_return(nil)
@@ -25,7 +25,7 @@ describe LegacyDiffNote, models: true do
end
it 'is never true when the note has no noteable associated' do
- note = build(:note_on_merge_request_diff)
+ note = build(:legacy_diff_note_on_merge_request)
expect(note).to receive(:diff).and_return(double)
expect(note).to receive(:noteable).and_return(nil)
@@ -34,7 +34,7 @@ describe LegacyDiffNote, models: true do
end
it 'returns the memoized value if defined' do
- note = build(:note_on_merge_request_diff)
+ note = build(:legacy_diff_note_on_merge_request)
note.instance_variable_set(:@active, 'foo')
expect(note).not_to receive(:find_noteable_diff)
@@ -45,7 +45,7 @@ describe LegacyDiffNote, models: true do
context 'for a merge request noteable' do
it 'is false when noteable has no matching diff' do
merge = build_stubbed(:merge_request, :simple)
- note = build(:note_on_merge_request_diff, noteable: merge)
+ note = build(:legacy_diff_note_on_merge_request, noteable: merge)
allow(note).to receive(:diff).and_return(double)
expect(note).to receive(:find_noteable_diff).and_return(nil)
@@ -63,9 +63,9 @@ describe LegacyDiffNote, models: true do
code = Gitlab::Diff::LineCode.generate(diff.new_path, line.new_pos, line.old_pos)
# We're persisting in order to trigger the set_diff callback
- note = create(:note_on_merge_request_diff, noteable: merge,
- line_code: code,
- project: merge.source_project)
+ note = create(:legacy_diff_note_on_merge_request, noteable: merge,
+ line_code: code,
+ project: merge.source_project)
# Make sure we don't get a false positive from a guard clause
expect(note).to receive(:find_noteable_diff).and_call_original
diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb
new file mode 100644
index 00000000000..9a637c94fbe
--- /dev/null
+++ b/spec/models/merge_request_diff_spec.rb
@@ -0,0 +1,47 @@
+require 'spec_helper'
+
+describe MergeRequestDiff, models: true do
+ describe '#diffs' do
+ let(:mr) { create(:merge_request, :with_diffs) }
+ let(:mr_diff) { mr.merge_request_diff }
+
+ context 'when the :ignore_whitespace_change option is set' do
+ it 'creates a new compare object instead of loading from the DB' do
+ expect(mr_diff).not_to receive(:load_diffs)
+ expect(Gitlab::Git::Compare).to receive(:new).and_call_original
+
+ mr_diff.diffs(ignore_whitespace_change: true)
+ end
+ end
+
+ context 'when the raw diffs are empty' do
+ before { mr_diff.update_attributes(st_diffs: '') }
+
+ it 'returns an empty DiffCollection' do
+ expect(mr_diff.diffs).to be_a(Gitlab::Git::DiffCollection)
+ expect(mr_diff.diffs).to be_empty
+ end
+ end
+
+ context 'when the raw diffs exist' do
+ it 'returns the diffs' do
+ expect(mr_diff.diffs).to be_a(Gitlab::Git::DiffCollection)
+ expect(mr_diff.diffs).not_to be_empty
+ end
+
+ context 'when the :paths option is set' do
+ let(:diffs) { mr_diff.diffs(paths: ['files/ruby/popen.rb', 'files/ruby/popen.rb']) }
+
+ it 'only returns diffs that match the (old path, new path) given' do
+ expect(diffs.map(&:new_path)).to contain_exactly('files/ruby/popen.rb')
+ end
+
+ it 'uses the diffs from the DB' do
+ expect(mr_diff).to receive(:load_diffs)
+
+ diffs
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index ceb4d64698f..c8ad7ab3e7f 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe MergeRequest, models: true do
+ include RepoHelpers
+
subject { create(:merge_request) }
describe 'associations' do
@@ -62,7 +64,7 @@ describe MergeRequest, models: true do
end
end
- describe '#target_sha' do
+ describe '#target_branch_sha' do
context 'when the target branch does not exist anymore' do
let(:project) { create(:project) }
@@ -73,32 +75,32 @@ describe MergeRequest, models: true do
end
it 'returns nil' do
- expect(subject.target_sha).to be_nil
+ expect(subject.target_branch_sha).to be_nil
end
end
end
- describe '#source_sha' do
+ describe '#source_branch_sha' do
let(:last_branch_commit) { subject.source_project.repository.commit(subject.source_branch) }
context 'with diffs' do
subject { create(:merge_request, :with_diffs) }
it 'returns the sha of the source branch last commit' do
- expect(subject.source_sha).to eq(last_branch_commit.sha)
+ expect(subject.source_branch_sha).to eq(last_branch_commit.sha)
end
end
context 'without diffs' do
subject { create(:merge_request, :without_diffs) }
it 'returns the sha of the source branch last commit' do
- expect(subject.source_sha).to eq(last_branch_commit.sha)
+ expect(subject.source_branch_sha).to eq(last_branch_commit.sha)
end
end
context 'when the merge request is being created' do
subject { build(:merge_request, source_branch: nil, compare_commits: []) }
it 'returns nil' do
- expect(subject.source_sha).to be_nil
+ expect(subject.source_branch_sha).to be_nil
end
end
end
@@ -114,6 +116,31 @@ describe MergeRequest, models: true do
end
end
+ describe '#diffs' do
+ let(:merge_request) { build(:merge_request) }
+ let(:options) { { paths: ['a/b', 'b/a', 'c/*'] } }
+
+ context 'when there are MR diffs' do
+ it 'delegates to the MR diffs' do
+ merge_request.merge_request_diff = MergeRequestDiff.new
+
+ expect(merge_request.merge_request_diff).to receive(:diffs).with(options)
+
+ merge_request.diffs(options)
+ end
+ end
+
+ context 'when there are no MR diffs' do
+ it 'delegates to the compare object' do
+ merge_request.compare = double(:compare)
+
+ expect(merge_request.compare).to receive(:diffs).with(options)
+
+ merge_request.diffs(options)
+ end
+ end
+ end
+
describe "#mr_and_commit_notes" do
let!(:merge_request) { create(:merge_request) }
@@ -252,12 +279,14 @@ describe MergeRequest, models: true do
end
it "can be removed if the last commit is the head of the source branch" do
- allow(subject.source_project).to receive(:commit).and_return(subject.last_commit)
+ allow(subject.source_project).to receive(:commit).and_return(subject.diff_head_commit)
expect(subject.can_remove_source_branch?(user)).to be_truthy
end
it "cannot be removed if the last commit is not also the head of the source branch" do
+ subject.source_branch = "lfs"
+
expect(subject.can_remove_source_branch?(user)).to be_falsey
end
end
@@ -363,7 +392,7 @@ describe MergeRequest, models: true do
and_return(2)
subject.diverged_commits_count
- allow(subject).to receive(:source_sha).and_return('123abc')
+ allow(subject).to receive(:source_branch_sha).and_return('123abc')
subject.diverged_commits_count
end
@@ -373,7 +402,7 @@ describe MergeRequest, models: true do
and_return(2)
subject.diverged_commits_count
- allow(subject).to receive(:target_sha).and_return('123abc')
+ allow(subject).to receive(:target_branch_sha).and_return('123abc')
subject.diverged_commits_count
end
end
@@ -392,11 +421,10 @@ describe MergeRequest, models: true do
describe '#pipeline' do
describe 'when the source project exists' do
- it 'returns the latest commit' do
- commit = double(:commit, id: '123abc')
+ it 'returns the latest pipeline' do
pipeline = double(:ci_pipeline, ref: 'master')
- allow(subject).to receive(:last_commit).and_return(commit)
+ allow(subject).to receive(:diff_head_sha).and_return('123abc')
expect(subject.source_project).to receive(:pipeline).
with('123abc', 'master').
@@ -464,7 +492,7 @@ describe MergeRequest, models: true do
context 'when it is not broken and has no conflicts' do
it 'is marked as mergeable' do
allow(subject).to receive(:broken?) { false }
- allow(project.repository).to receive(:can_be_merged?) { true }
+ allow(project.repository).to receive(:can_be_merged?).and_return(true)
expect { subject.check_if_can_be_merged }.to change { subject.merge_status }.to('can_be_merged')
end
@@ -481,7 +509,7 @@ describe MergeRequest, models: true do
context 'when it has conflicts' do
before do
allow(subject).to receive(:broken?) { false }
- allow(project.repository).to receive(:can_be_merged?) { false }
+ allow(project.repository).to receive(:can_be_merged?).and_return(false)
end
it 'becomes unmergeable' do
@@ -608,4 +636,42 @@ describe MergeRequest, models: true do
end
end
end
+
+ describe "#reload_diff" do
+ let(:note) { create(:diff_note_on_merge_request, project: subject.project, noteable: subject) }
+
+ let(:commit) { subject.project.commit(sample_commit.id) }
+
+ it "reloads the diff content" do
+ expect(subject.merge_request_diff).to receive(:reload_content)
+
+ subject.reload_diff
+ end
+
+ it "updates diff note positions" do
+ old_diff_refs = subject.diff_refs
+
+ merge_request_diff = subject.merge_request_diff
+
+ # Update merge_request_diff so that #diff_refs will return commit.diff_refs
+ allow(merge_request_diff).to receive(:reload_content) do
+ merge_request_diff.base_commit_sha = commit.parent_id
+ merge_request_diff.start_commit_sha = commit.parent_id
+ merge_request_diff.head_commit_sha = commit.sha
+ end
+
+ expect(Notes::DiffPositionUpdateService).to receive(:new).with(
+ subject.project,
+ nil,
+ old_diff_refs: old_diff_refs,
+ new_diff_refs: commit.diff_refs,
+ paths: note.position.paths
+ ).and_call_original
+ expect_any_instance_of(Notes::DiffPositionUpdateService).to receive(:execute).with(note)
+
+ expect_any_instance_of(DiffNote).to receive(:save).once
+
+ subject.reload_diff
+ end
+ end
end
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index 6549791f675..7d0697dab42 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -226,6 +226,20 @@ describe Note, models: true do
it "returns false" do
expect(note.cross_reference_not_visible_for?(private_user)).to be_falsy
end
+
+ it "returns false if user visible reference count set" do
+ note.user_visible_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
describe 'clear_blank_line_code!' do
diff --git a/spec/models/notification_setting_spec.rb b/spec/models/notification_setting_spec.rb
index df336a6effe..d58673413c8 100644
--- a/spec/models/notification_setting_spec.rb
+++ b/spec/models/notification_setting_spec.rb
@@ -38,4 +38,21 @@ RSpec.describe NotificationSetting, type: :model do
end
end
end
+
+ describe '#for_projects' do
+ let(:user) { create(:user) }
+
+ before do
+ 1.upto(4) do |i|
+ setting = create(:notification_setting, user: user)
+
+ setting.project.update_attributes(pending_delete: true) if i.even?
+ end
+ end
+
+ it 'excludes projects pending delete' do
+ expect(user.notification_settings.for_projects).to all(have_attributes(project: an_instance_of(Project)))
+ expect(user.notification_settings.for_projects.map(&:project)).to all(have_attributes(pending_delete: false))
+ end
+ end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index a8c777d1e3e..5a27ccbab0a 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -129,6 +129,18 @@ describe Project, models: true do
expect(project2.errors[:repository_storage].first).to match(/is not included in the list/)
end
end
+
+ it 'should not allow an invalid URI as import_url' do
+ project2 = build(:project, import_url: 'invalid://')
+
+ expect(project2).not_to be_valid
+ end
+
+ it 'should allow a valid URI as import_url' do
+ project2 = build(:project, import_url: 'ssh://test@gitlab.com/project.git')
+
+ expect(project2).to be_valid
+ end
end
describe 'default_scope' do
@@ -300,7 +312,7 @@ describe Project, models: true do
it 'should update merge request commits with new one if pushed to source branch' do
project.update_merge_requests(prev_commit_id, commit_id, "refs/heads/#{merge_request.source_branch}", key.user)
merge_request.reload
- expect(merge_request.last_commit.id).to eq(commit_id)
+ expect(merge_request.diff_head_sha).to eq(commit_id)
end
end
@@ -437,6 +449,14 @@ describe Project, models: true do
it { expect(project.open_branches.map(&:name)).to include('feature') }
it { expect(project.open_branches.map(&:name)).not_to include('master') }
+
+ it "includes branches matching a protected branch wildcard" do
+ expect(project.open_branches.map(&:name)).to include('feature')
+
+ create(:protected_branch, name: 'feat*', project: project)
+
+ expect(Project.find(project.id).open_branches.map(&:name)).to include('feature')
+ end
end
describe '#star_count' do
@@ -937,15 +957,67 @@ describe Project, models: true do
describe '#protected_branch?' do
let(:project) { create(:empty_project) }
- it 'returns true when a branch is a protected branch' do
+ it 'returns true when the branch matches a protected branch via direct match' do
project.protected_branches.create!(name: 'foo')
expect(project.protected_branch?('foo')).to eq(true)
end
- it 'returns false when a branch is not a protected branch' do
+ it 'returns true when the branch matches a protected branch via wildcard match' do
+ project.protected_branches.create!(name: 'production/*')
+
+ expect(project.protected_branch?('production/some-branch')).to eq(true)
+ end
+
+ it 'returns false when the branch does not match a protected branch via direct match' do
expect(project.protected_branch?('foo')).to eq(false)
end
+
+ it 'returns false when the branch does not match a protected branch via wildcard match' do
+ project.protected_branches.create!(name: 'production/*')
+
+ expect(project.protected_branch?('staging/some-branch')).to eq(false)
+ end
+ end
+
+ describe "#developers_can_push_to_protected_branch?" do
+ let(:project) { create(:empty_project) }
+
+ context "when the branch matches a protected branch via direct match" do
+ it "returns true if 'Developers can Push' is turned on" do
+ create(:protected_branch, name: "production", project: project, developers_can_push: true)
+
+ expect(project.developers_can_push_to_protected_branch?('production')).to be true
+ end
+
+ it "returns false if 'Developers can Push' is turned off" do
+ create(:protected_branch, name: "production", project: project, developers_can_push: false)
+
+ expect(project.developers_can_push_to_protected_branch?('production')).to be false
+ end
+ end
+
+ context "when the branch matches a protected branch via wilcard match" do
+ it "returns true if 'Developers can Push' is turned on" do
+ create(:protected_branch, name: "production/*", project: project, developers_can_push: true)
+
+ expect(project.developers_can_push_to_protected_branch?('production/some-branch')).to be true
+ end
+
+ it "returns false if 'Developers can Push' is turned off" do
+ create(:protected_branch, name: "production/*", project: project, developers_can_push: false)
+
+ expect(project.developers_can_push_to_protected_branch?('production/some-branch')).to be false
+ end
+ end
+
+ context "when the branch does not match a protected branch" do
+ it "returns false" do
+ create(:protected_branch, name: "production/*", project: project, developers_can_push: true)
+
+ expect(project.developers_can_push_to_protected_branch?('staging/some-branch')).to be false
+ end
+ end
end
describe '#container_registry_path_with_namespace' do
diff --git a/spec/models/protected_branch_spec.rb b/spec/models/protected_branch_spec.rb
index b523834c6e9..8bf0d24a128 100644
--- a/spec/models/protected_branch_spec.rb
+++ b/spec/models/protected_branch_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe ProtectedBranch, models: true do
+ subject { build_stubbed(:protected_branch) }
+
describe 'Associations' do
it { is_expected.to belong_to(:project) }
end
@@ -12,4 +14,127 @@ describe ProtectedBranch, models: true do
it { is_expected.to validate_presence_of(:project) }
it { is_expected.to validate_presence_of(:name) }
end
+
+ describe "#matches?" do
+ context "when the protected branch setting is not a wildcard" do
+ let(:protected_branch) { build(:protected_branch, name: "production/some-branch") }
+
+ it "returns true for branch names that are an exact match" do
+ expect(protected_branch.matches?("production/some-branch")).to be true
+ end
+
+ it "returns false for branch names that are not an exact match" do
+ expect(protected_branch.matches?("staging/some-branch")).to be false
+ end
+ end
+
+ context "when the protected branch name contains wildcard(s)" do
+ context "when there is a single '*'" do
+ let(:protected_branch) { build(:protected_branch, name: "production/*") }
+
+ it "returns true for branch names matching the wildcard" do
+ expect(protected_branch.matches?("production/some-branch")).to be true
+ expect(protected_branch.matches?("production/")).to be true
+ end
+
+ it "returns false for branch names not matching the wildcard" do
+ expect(protected_branch.matches?("staging/some-branch")).to be false
+ expect(protected_branch.matches?("production")).to be false
+ end
+ end
+
+ context "when the wildcard contains regex symbols other than a '*'" do
+ let(:protected_branch) { build(:protected_branch, name: "pro.duc.tion/*") }
+
+ it "returns true for branch names matching the wildcard" do
+ expect(protected_branch.matches?("pro.duc.tion/some-branch")).to be true
+ end
+
+ it "returns false for branch names not matching the wildcard" do
+ expect(protected_branch.matches?("production/some-branch")).to be false
+ expect(protected_branch.matches?("proXducYtion/some-branch")).to be false
+ end
+ end
+
+ context "when there are '*'s at either end" do
+ let(:protected_branch) { build(:protected_branch, name: "*/production/*") }
+
+ it "returns true for branch names matching the wildcard" do
+ expect(protected_branch.matches?("gitlab/production/some-branch")).to be true
+ expect(protected_branch.matches?("/production/some-branch")).to be true
+ expect(protected_branch.matches?("gitlab/production/")).to be true
+ expect(protected_branch.matches?("/production/")).to be true
+ end
+
+ it "returns false for branch names not matching the wildcard" do
+ expect(protected_branch.matches?("gitlabproductionsome-branch")).to be false
+ expect(protected_branch.matches?("production/some-branch")).to be false
+ expect(protected_branch.matches?("gitlab/production")).to be false
+ expect(protected_branch.matches?("production")).to be false
+ end
+ end
+
+ context "when there are arbitrarily placed '*'s" do
+ let(:protected_branch) { build(:protected_branch, name: "pro*duction/*/gitlab/*") }
+
+ it "returns true for branch names matching the wildcard" do
+ expect(protected_branch.matches?("production/some-branch/gitlab/second-branch")).to be true
+ expect(protected_branch.matches?("proXYZduction/some-branch/gitlab/second-branch")).to be true
+ expect(protected_branch.matches?("proXYZduction/gitlab/gitlab/gitlab")).to be true
+ expect(protected_branch.matches?("proXYZduction//gitlab/")).to be true
+ expect(protected_branch.matches?("proXYZduction/some-branch/gitlab/")).to be true
+ expect(protected_branch.matches?("proXYZduction//gitlab/some-branch")).to be true
+ end
+
+ it "returns false for branch names not matching the wildcard" do
+ expect(protected_branch.matches?("production/some-branch/not-gitlab/second-branch")).to be false
+ expect(protected_branch.matches?("prodXYZuction/some-branch/gitlab/second-branch")).to be false
+ expect(protected_branch.matches?("proXYZduction/gitlab/some-branch/gitlab")).to be false
+ expect(protected_branch.matches?("proXYZduction/gitlab//")).to be false
+ expect(protected_branch.matches?("proXYZduction/gitlab/")).to be false
+ expect(protected_branch.matches?("proXYZduction//some-branch/gitlab")).to be false
+ end
+ end
+ end
+ end
+
+ describe "#matching" do
+ context "for direct matches" do
+ it "returns a list of protected branches matching the given branch name" do
+ production = create(:protected_branch, name: "production")
+ staging = create(:protected_branch, name: "staging")
+
+ expect(ProtectedBranch.matching("production")).to include(production)
+ expect(ProtectedBranch.matching("production")).not_to include(staging)
+ end
+
+ it "accepts a list of protected branches to search from, so as to avoid a DB call" do
+ production = build(:protected_branch, name: "production")
+ staging = build(:protected_branch, name: "staging")
+
+ expect(ProtectedBranch.matching("production")).to be_empty
+ expect(ProtectedBranch.matching("production", protected_branches: [production, staging])).to include(production)
+ expect(ProtectedBranch.matching("production", protected_branches: [production, staging])).not_to include(staging)
+ end
+ end
+
+ context "for wildcard matches" do
+ it "returns a list of protected branches matching the given branch name" do
+ production = create(:protected_branch, name: "production/*")
+ staging = create(:protected_branch, name: "staging/*")
+
+ expect(ProtectedBranch.matching("production/some-branch")).to include(production)
+ expect(ProtectedBranch.matching("production/some-branch")).not_to include(staging)
+ end
+
+ it "accepts a list of protected branches to search from, so as to avoid a DB call" do
+ production = build(:protected_branch, name: "production/*")
+ staging = build(:protected_branch, name: "staging/*")
+
+ expect(ProtectedBranch.matching("production/some-branch")).to be_empty
+ expect(ProtectedBranch.matching("production/some-branch", protected_branches: [production, staging])).to include(production)
+ expect(ProtectedBranch.matching("production/some-branch", protected_branches: [production, staging])).not_to include(staging)
+ end
+ end
+ end
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 7975fc64e59..24e49c8def3 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -12,8 +12,8 @@ describe Repository, models: true do
end
let(:merge_commit) do
source_sha = repository.find_branch('feature').target
- merge_commit_id = repository.merge(user, source_sha, 'master', commit_options)
- repository.commit(merge_commit_id)
+ merge_commit_sha = repository.merge(user, source_sha, 'master', commit_options)
+ repository.commit(merge_commit_sha)
end
describe :branch_names_contains do
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 328254ed56b..3984b30ddf8 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -446,6 +446,7 @@ describe User, models: true do
it { expect(user.can_create_group?).to be_truthy }
it { expect(user.can_create_project?).to be_truthy }
it { expect(user.first_name).to eq('John') }
+ it { expect(user.external).to be_falsey }
end
describe 'with defaults' do
@@ -468,6 +469,26 @@ describe User, models: true do
expect(user.theme_id).to eq(1)
end
end
+
+ context 'when current_application_settings.user_default_external is true' do
+ before do
+ stub_application_setting(user_default_external: true)
+ end
+
+ it "creates external user by default" do
+ user = build(:user)
+
+ expect(user.external).to be_truthy
+ end
+
+ describe 'with default overrides' do
+ it "creates a non-external user" do
+ user = build(:user, external: false)
+
+ expect(user.external).to be_falsey
+ end
+ end
+ end
end
describe '.find_by_any_email' do
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 04141a45031..c2c94040ece 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -49,10 +49,25 @@ describe API::API, api: true do
describe "GET /groups/:id" do
context "when authenticated as user" do
- it "should return one of user1's groups" do
+ it "returns one of user1's groups" do
+ project = create(:project, namespace: group2, path: 'Foo')
+ create(:project_group_link, project: project, group: group1)
+
get api("/groups/#{group1.id}", user1)
+
expect(response).to have_http_status(200)
- json_response['name'] == group1.name
+ expect(json_response['id']).to eq(group1.id)
+ expect(json_response['name']).to eq(group1.name)
+ expect(json_response['path']).to eq(group1.path)
+ expect(json_response['description']).to eq(group1.description)
+ expect(json_response['visibility_level']).to eq(group1.visibility_level)
+ expect(json_response['avatar_url']).to eq(group1.avatar_url)
+ expect(json_response['web_url']).to eq(group1.web_url)
+ expect(json_response['projects']).to be_an Array
+ expect(json_response['projects'].length).to eq(2)
+ expect(json_response['shared_projects']).to be_an Array
+ expect(json_response['shared_projects'].length).to eq(1)
+ expect(json_response['shared_projects'][0]['id']).to eq(project.id)
end
it "should not return a non existing group" do
diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb
index fcea45f19ba..e567d36afa8 100644
--- a/spec/requests/api/internal_spec.rb
+++ b/spec/requests/api/internal_spec.rb
@@ -207,26 +207,86 @@ describe API::API, api: true do
expect(json_response["status"]).to be_falsey
end
end
+
+ context 'ssh access has been disabled' do
+ before do
+ settings = ::ApplicationSetting.create_from_defaults
+ settings.update_attribute(:enabled_git_access_protocol, 'http')
+ end
+
+ it 'rejects the SSH push' do
+ push(key, project)
+
+ expect(response.status).to eq(200)
+ expect(json_response['status']).to be_falsey
+ expect(json_response['message']).to eq 'Git access over SSH is not allowed'
+ end
+
+ it 'rejects the SSH pull' do
+ pull(key, project)
+
+ expect(response.status).to eq(200)
+ expect(json_response['status']).to be_falsey
+ expect(json_response['message']).to eq 'Git access over SSH is not allowed'
+ end
+ end
+
+ context 'http access has been disabled' do
+ before do
+ settings = ::ApplicationSetting.create_from_defaults
+ settings.update_attribute(:enabled_git_access_protocol, 'ssh')
+ end
+
+ it 'rejects the HTTP push' do
+ push(key, project, 'http')
+
+ expect(response.status).to eq(200)
+ expect(json_response['status']).to be_falsey
+ expect(json_response['message']).to eq 'Git access over HTTP is not allowed'
+ end
+
+ it 'rejects the HTTP pull' do
+ pull(key, project, 'http')
+
+ expect(response.status).to eq(200)
+ expect(json_response['status']).to be_falsey
+ expect(json_response['message']).to eq 'Git access over HTTP is not allowed'
+ end
+ end
+
+ context 'web actions are always allowed' do
+ it 'allows WEB push' do
+ settings = ::ApplicationSetting.create_from_defaults
+ settings.update_attribute(:enabled_git_access_protocol, 'ssh')
+ project.team << [user, :developer]
+ push(key, project, 'web')
+
+ expect(response.status).to eq(200)
+ expect(json_response['status']).to be_truthy
+ end
+ end
end
- def pull(key, project)
+ def pull(key, project, protocol = 'ssh')
post(
api("/internal/allowed"),
key_id: key.id,
project: project.path_with_namespace,
action: 'git-upload-pack',
- secret_token: secret_token
+ secret_token: secret_token,
+ protocol: protocol
)
end
- def push(key, project)
+ def push(key, project, protocol = 'ssh')
post(
api("/internal/allowed"),
changes: 'd14d6c0abdd253381df51a723d58691b2ee1ab08 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master',
key_id: key.id,
project: project.path_with_namespace,
action: 'git-receive-pack',
- secret_token: secret_token
+ secret_token: secret_token,
+ protocol: protocol
)
end
@@ -237,7 +297,8 @@ describe API::API, api: true do
key_id: key.id,
project: project.path_with_namespace,
action: 'git-upload-archive',
- secret_token: secret_token
+ secret_token: secret_token,
+ protocol: 'ssh'
)
end
end
diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
index 2cf130df328..6adccb4ebae 100644
--- a/spec/requests/api/issues_spec.rb
+++ b/spec/requests/api/issues_spec.rb
@@ -482,12 +482,16 @@ describe API::API, api: true do
expect(response).to have_http_status(400)
end
- it 'should return 400 on invalid label names' do
+ it 'should allow special label names' do
post api("/projects/#{project.id}/issues", user),
title: 'new issue',
- labels: 'label, ?'
- expect(response).to have_http_status(400)
- expect(json_response['message']['labels']['?']['title']).to eq(['is invalid'])
+ labels: 'label, label?, label&foo, ?, &'
+ expect(response.status).to eq(201)
+ expect(json_response['labels']).to include 'label'
+ expect(json_response['labels']).to include 'label?'
+ expect(json_response['labels']).to include 'label&foo'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
end
it 'should return 400 if title is too long' do
@@ -557,12 +561,17 @@ describe API::API, api: true do
expect(response).to have_http_status(404)
end
- it 'should return 400 on invalid label names' do
+ it 'should allow special label names' do
put api("/projects/#{project.id}/issues/#{issue.id}", user),
title: 'updated title',
- labels: 'label, ?'
- expect(response).to have_http_status(400)
- expect(json_response['message']['labels']['?']['title']).to eq(['is invalid'])
+ labels: 'label, label?, label&foo, ?, &'
+
+ expect(response.status).to eq(200)
+ expect(json_response['labels']).to include 'label'
+ expect(json_response['labels']).to include 'label?'
+ expect(json_response['labels']).to include 'label&foo'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
end
context 'confidential issues' do
@@ -627,21 +636,18 @@ describe API::API, api: true do
expect(json_response['labels']).to include 'bar'
end
- it 'should return 400 on invalid label names' do
- put api("/projects/#{project.id}/issues/#{issue.id}", user),
- labels: 'label, ?'
- expect(response).to have_http_status(400)
- expect(json_response['message']['labels']['?']['title']).to eq(['is invalid'])
- end
-
it 'should allow special label names' do
put api("/projects/#{project.id}/issues/#{issue.id}", user),
- labels: 'label:foo, label-bar,label_bar,label/bar'
- expect(response).to have_http_status(200)
+ labels: 'label:foo, label-bar,label_bar,label/bar,label?bar,label&bar,?,&'
+ expect(response.status).to eq(200)
expect(json_response['labels']).to include 'label:foo'
expect(json_response['labels']).to include 'label-bar'
expect(json_response['labels']).to include 'label_bar'
expect(json_response['labels']).to include 'label/bar'
+ expect(json_response['labels']).to include 'label?bar'
+ expect(json_response['labels']).to include 'label&bar'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
end
it 'should return 400 if title is too long' do
diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb
index 0404cf31ff7..63636b4a1b6 100644
--- a/spec/requests/api/labels_spec.rb
+++ b/spec/requests/api/labels_spec.rb
@@ -35,10 +35,10 @@ describe API::API, api: true do
it 'should return created label when only required params' do
post api("/projects/#{project.id}/labels", user),
- name: 'Foo',
+ name: 'Foo & Bar',
color: '#FFAABB'
- expect(response).to have_http_status(201)
- expect(json_response['name']).to eq('Foo')
+ expect(response.status).to eq(201)
+ expect(json_response['name']).to eq('Foo & Bar')
expect(json_response['color']).to eq('#FFAABB')
expect(json_response['description']).to be_nil
end
@@ -71,7 +71,7 @@ describe API::API, api: true do
it 'should return 400 for invalid name' do
post api("/projects/#{project.id}/labels", user),
- name: '?',
+ name: ',',
color: '#FFAABB'
expect(response).to have_http_status(400)
expect(json_response['message']['title']).to eq(['is invalid'])
@@ -167,7 +167,7 @@ describe API::API, api: true do
it 'should return 400 for invalid name' do
put api("/projects/#{project.id}/labels", user),
name: 'label1',
- new_name: '?',
+ new_name: ',',
color: '#FFFFFF'
expect(response).to have_http_status(400)
expect(json_response['message']['title']).to eq(['is invalid'])
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 61e897edf87..651b91e9f68 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -138,6 +138,8 @@ describe API::API, api: true do
expect(json_response['work_in_progress']).to be_falsy
expect(json_response['merge_when_build_succeeds']).to be_falsy
expect(json_response['merge_status']).to eq('can_be_merged')
+ expect(json_response['should_close_merge_request']).to be_falsy
+ expect(json_response['force_close_merge_request']).to be_falsy
end
it "should return merge_request" do
@@ -147,6 +149,8 @@ describe API::API, api: true do
expect(json_response['iid']).to eq(merge_request.iid)
expect(json_response['work_in_progress']).to eq(false)
expect(json_response['merge_status']).to eq('can_be_merged')
+ expect(json_response['should_close_merge_request']).to be_falsy
+ expect(json_response['force_close_merge_request']).to be_falsy
end
it 'should return merge_request by iid' do
@@ -243,17 +247,19 @@ describe API::API, api: true do
expect(response).to have_http_status(400)
end
- it 'should return 400 on invalid label names' do
+ it 'should allow special label names' do
post api("/projects/#{project.id}/merge_requests", user),
title: 'Test merge_request',
source_branch: 'markdown',
target_branch: 'master',
author: user,
- labels: 'label, ?'
- expect(response).to have_http_status(400)
- expect(json_response['message']['labels']['?']['title']).to eq(
- ['is invalid']
- )
+ labels: 'label, label?, label&foo, ?, &'
+ expect(response.status).to eq(201)
+ expect(json_response['labels']).to include 'label'
+ expect(json_response['labels']).to include 'label?'
+ expect(json_response['labels']).to include 'label&foo'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
end
context 'with existing MR' do
@@ -437,14 +443,14 @@ describe API::API, api: true do
end
it "returns 409 if the SHA parameter doesn't match" do
- put api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user), sha: merge_request.source_sha.succ
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user), sha: merge_request.diff_head_sha.reverse
expect(response).to have_http_status(409)
expect(json_response['message']).to start_with('SHA does not match HEAD of source branch')
end
it "succeeds if the SHA parameter matches" do
- put api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user), sha: merge_request.source_sha
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user), sha: merge_request.diff_head_sha
expect(response).to have_http_status(200)
end
@@ -492,13 +498,17 @@ describe API::API, api: true do
expect(json_response['target_branch']).to eq('wiki')
end
- it 'should return 400 on invalid label names' do
+ it 'should allow special label names' do
put api("/projects/#{project.id}/merge_requests/#{merge_request.id}",
user),
title: 'new issue',
- labels: 'label, ?'
- expect(response).to have_http_status(400)
- expect(json_response['message']['labels']['?']['title']).to eq(['is invalid'])
+ labels: 'label, label?, label&foo, ?, &'
+ expect(response.status).to eq(200)
+ expect(json_response['labels']).to include 'label'
+ expect(json_response['labels']).to include 'label?'
+ expect(json_response['labels']).to include 'label&foo'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
end
end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 6ded6b40178..23b0a2a8885 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -402,11 +402,47 @@ describe API::API, api: true do
before { project }
before { project_member }
- it 'should return a project by id' do
+ it 'returns a project by id' do
+ group = create(:group)
+ link = create(:project_group_link, project: project, group: group)
+
get api("/projects/#{project.id}", user)
+
expect(response).to have_http_status(200)
+ expect(json_response['id']).to eq(project.id)
+ expect(json_response['description']).to eq(project.description)
+ expect(json_response['default_branch']).to eq(project.default_branch)
+ expect(json_response['tag_list']).to be_an Array
+ expect(json_response['public']).to be_falsey
+ expect(json_response['archived']).to be_falsey
+ expect(json_response['visibility_level']).to be_present
+ expect(json_response['ssh_url_to_repo']).to be_present
+ expect(json_response['http_url_to_repo']).to be_present
+ expect(json_response['web_url']).to be_present
+ expect(json_response['owner']).to be_a Hash
+ expect(json_response['owner']).to be_a Hash
expect(json_response['name']).to eq(project.name)
- expect(json_response['owner']['username']).to eq(user.username)
+ expect(json_response['path']).to be_present
+ expect(json_response['issues_enabled']).to be_present
+ expect(json_response['merge_requests_enabled']).to be_present
+ expect(json_response['wiki_enabled']).to be_present
+ expect(json_response['builds_enabled']).to be_present
+ expect(json_response['snippets_enabled']).to be_present
+ expect(json_response['container_registry_enabled']).to be_present
+ expect(json_response['created_at']).to be_present
+ expect(json_response['last_activity_at']).to be_present
+ expect(json_response['shared_runners_enabled']).to be_present
+ expect(json_response['creator_id']).to be_present
+ expect(json_response['namespace']).to be_present
+ expect(json_response['avatar_url']).to be_nil
+ expect(json_response['star_count']).to be_present
+ expect(json_response['forks_count']).to be_present
+ expect(json_response['public_builds']).to be_present
+ expect(json_response['shared_with_groups']).to be_an Array
+ expect(json_response['shared_with_groups'].length).to eq(1)
+ expect(json_response['shared_with_groups'][0]['group_id']).to eq(group.id)
+ expect(json_response['shared_with_groups'][0]['group_name']).to eq(group.name)
+ expect(json_response['shared_with_groups'][0]['group_access_level']).to eq(link.group_access)
end
it 'should return a project by path name' do
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index 8a8e131c57b..2c755919456 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -98,7 +98,7 @@ describe SnippetsController, "routing" do
end
# help GET /help(.:format) help#index
-# help_page GET /help/:category/:file(.:format) help#show {:category=>/.*/, :file=>/[^\/\.]+/}
+# help_page GET /help/*path(.:format) help#show
# help_shortcuts GET /help/shortcuts(.:format) help#shortcuts
# help_ui GET /help/ui(.:format) help#ui
describe HelpController, "routing" do
@@ -109,23 +109,19 @@ describe HelpController, "routing" do
it 'to #show' do
path = '/help/markdown/markdown.md'
expect(get(path)).to route_to('help#show',
- category: 'markdown',
- file: 'markdown',
+ path: 'markdown/markdown',
format: 'md')
path = '/help/workflow/protected_branches/protected_branches1.png'
expect(get(path)).to route_to('help#show',
- category: 'workflow/protected_branches',
- file: 'protected_branches1',
+ path: 'workflow/protected_branches/protected_branches1',
format: 'png')
- end
-
- it 'to #shortcuts' do
- expect(get('/help/shortcuts')).to route_to('help#shortcuts')
- end
-
- it 'to #ui' do
- expect(get('/help/ui')).to route_to('help#ui')
+ path = '/help/shortcuts'
+ expect(get(path)).to route_to('help#show',
+ path: 'shortcuts')
+ path = '/help/ui'
+ expect(get(path)).to route_to('help#show',
+ path: 'ui')
end
end
diff --git a/spec/services/notes/diff_position_update_service_spec.rb b/spec/services/notes/diff_position_update_service_spec.rb
new file mode 100644
index 00000000000..110efb54fa0
--- /dev/null
+++ b/spec/services/notes/diff_position_update_service_spec.rb
@@ -0,0 +1,175 @@
+require 'spec_helper'
+
+describe Notes::DiffPositionUpdateService, services: true do
+ let(:project) { create(:project) }
+ let(:create_commit) { project.commit("913c66a37b4a45b9769037c55c2d238bd0942d2e") }
+ let(:modify_commit) { project.commit("874797c3a73b60d2187ed6e2fcabd289ff75171e") }
+ let(:edit_commit) { project.commit("570e7b2abdd848b95f2f578043fc23bd6f6fd24d") }
+
+ let(:path) { "files/ruby/popen.rb" }
+
+ let(:old_diff_refs) do
+ Gitlab::Diff::DiffRefs.new(
+ base_sha: create_commit.parent_id,
+ head_sha: modify_commit.sha
+ )
+ end
+
+ let(:new_diff_refs) do
+ Gitlab::Diff::DiffRefs.new(
+ base_sha: create_commit.parent_id,
+ head_sha: edit_commit.sha
+ )
+ end
+
+ subject do
+ described_class.new(
+ project,
+ nil,
+ old_diff_refs: old_diff_refs,
+ new_diff_refs: new_diff_refs,
+ paths: [path]
+ )
+ end
+
+ # old diff:
+ # 1 + require 'fileutils'
+ # 2 + require 'open3'
+ # 3 +
+ # 4 + module Popen
+ # 5 + extend self
+ # 6 +
+ # 7 + def popen(cmd, path=nil)
+ # 8 + unless cmd.is_a?(Array)
+ # 9 + raise "System commands must be given as an array of strings"
+ # 10 + end
+ # 11 +
+ # 12 + path ||= Dir.pwd
+ # 13 + vars = { "PWD" => path }
+ # 14 + options = { chdir: path }
+ # 15 +
+ # 16 + unless File.directory?(path)
+ # 17 + FileUtils.mkdir_p(path)
+ # 18 + end
+ # 19 +
+ # 20 + @cmd_output = ""
+ # 21 + @cmd_status = 0
+ # 22 + Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|
+ # 23 + @cmd_output << stdout.read
+ # 24 + @cmd_output << stderr.read
+ # 25 + @cmd_status = wait_thr.value.exitstatus
+ # 26 + end
+ # 27 +
+ # 28 + return @cmd_output, @cmd_status
+ # 29 + end
+ # 30 + end
+ #
+ # new diff:
+ # 1 + require 'fileutils'
+ # 2 + require 'open3'
+ # 3 +
+ # 4 + module Popen
+ # 5 + extend self
+ # 6 +
+ # 7 + def popen(cmd, path=nil)
+ # 8 + unless cmd.is_a?(Array)
+ # 9 + raise RuntimeError, "System commands must be given as an array of strings"
+ # 10 + end
+ # 11 +
+ # 12 + path ||= Dir.pwd
+ # 13 +
+ # 14 + vars = {
+ # 15 + "PWD" => path
+ # 16 + }
+ # 17 +
+ # 18 + options = {
+ # 19 + chdir: path
+ # 20 + }
+ # 21 +
+ # 22 + unless File.directory?(path)
+ # 23 + FileUtils.mkdir_p(path)
+ # 24 + end
+ # 25 +
+ # 26 + @cmd_output = ""
+ # 27 + @cmd_status = 0
+ # 28 +
+ # 29 + Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|
+ # 30 + @cmd_output << stdout.read
+ # 31 + @cmd_output << stderr.read
+ # 32 + @cmd_status = wait_thr.value.exitstatus
+ # 33 + end
+ # 34 +
+ # 35 + return @cmd_output, @cmd_status
+ # 36 + end
+ # 37 + end
+ #
+ # old->new diff:
+ # .. .. @@ -6,12 +6,18 @@ module Popen
+ # 6 6
+ # 7 7 def popen(cmd, path=nil)
+ # 8 8 unless cmd.is_a?(Array)
+ # 9 - raise "System commands must be given as an array of strings"
+ # 9 + raise RuntimeError, "System commands must be given as an array of strings"
+ # 10 10 end
+ # 11 11
+ # 12 12 path ||= Dir.pwd
+ # 13 - vars = { "PWD" => path }
+ # 14 - options = { chdir: path }
+ # 13 +
+ # 14 + vars = {
+ # 15 + "PWD" => path
+ # 16 + }
+ # 17 +
+ # 18 + options = {
+ # 19 + chdir: path
+ # 20 + }
+ # 15 21
+ # 16 22 unless File.directory?(path)
+ # 17 23 FileUtils.mkdir_p(path)
+ # 18 24 end
+ # 19 25
+ # 20 26 @cmd_output = ""
+ # 21 27 @cmd_status = 0
+ # 28 +
+ # 22 29 Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|
+ # 23 30 @cmd_output << stdout.read
+ # 24 31 @cmd_output << stderr.read
+ # .. ..
+
+ describe "#execute" do
+ let(:note) { create(:diff_note_on_merge_request, project: project, position: old_position) }
+
+ let(:old_position) do
+ Gitlab::Diff::Position.new(
+ old_path: path,
+ new_path: path,
+ old_line: nil,
+ new_line: line,
+ diff_refs: old_diff_refs
+ )
+ end
+
+ context "when the diff line is the same" do
+ let(:line) { 16 }
+
+ it "updates the position" do
+ subject.execute(note)
+
+ expect(note.original_position).to eq(old_position)
+ expect(note.position).not_to eq(old_position)
+ expect(note.position.new_line).to eq(22)
+ end
+ end
+
+ context "when the diff line has changed" do
+ let(:line) { 9 }
+
+ it "doesn't update the position" do
+ subject.execute(note)
+
+ expect(note.original_position).to eq(old_position)
+ expect(note.position).to eq(old_position)
+ end
+ end
+ end
+end
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 54719cbb8d8..d3dddfb4817 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -293,6 +293,30 @@ describe NotificationService, services: true do
end
end
end
+
+ context "merge request diff note" do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:merge_request) { create(:merge_request, source_project: project, assignee: user) }
+ let(:note) { create(:diff_note_on_merge_request, project: project, noteable: merge_request) }
+
+ before do
+ build_team(note.project)
+ project.team << [merge_request.author, :master]
+ project.team << [merge_request.assignee, :master]
+ end
+
+ describe :new_note do
+ it "records sent notifications" do
+ # Ensure create SentNotification by noteable = merge_request 6 times, not noteable = note
+ expect(SentNotification).to receive(:record_note).with(note, any_args).exactly(4).times.and_call_original
+
+ notification.new_note(note)
+
+ expect(SentNotification.last.position).to eq(note.position)
+ end
+ end
+ end
end
describe 'Issues' do
diff --git a/spec/services/projects/housekeeping_service_spec.rb b/spec/services/projects/housekeeping_service_spec.rb
index bd4dc6a0f79..7ab95e042ce 100644
--- a/spec/services/projects/housekeeping_service_spec.rb
+++ b/spec/services/projects/housekeeping_service_spec.rb
@@ -12,7 +12,7 @@ describe Projects::HousekeepingService do
it 'enqueues a sidekiq job' do
expect(subject).to receive(:try_obtain_lease).and_return(true)
- expect(GitlabShellOneShotWorker).to receive(:perform_async).with(:gc, project.repository_storage_path, project.path_with_namespace)
+ expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id)
subject.execute
expect(project.pushes_since_gc).to eq(0)
@@ -20,7 +20,7 @@ describe Projects::HousekeepingService do
it 'does not enqueue a job when no lease can be obtained' do
expect(subject).to receive(:try_obtain_lease).and_return(false)
- expect(GitlabShellOneShotWorker).not_to receive(:perform_async)
+ expect(GitGarbageCollectWorker).not_to receive(:perform_async)
expect { subject.execute }.to raise_error(Projects::HousekeepingService::LeaseTaken)
expect(project.pushes_since_gc).to eq(0)
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 85dd30bf48c..43693441450 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -213,7 +213,7 @@ describe SystemNoteService, services: true do
create(:merge_request, source_project: project, target_project: project)
end
- subject { described_class.merge_when_build_succeeds(noteable, project, author, noteable.last_commit) }
+ subject { described_class.merge_when_build_succeeds(noteable, project, author, noteable.diff_head_commit) }
it_behaves_like 'a system note'
diff --git a/spec/support/capybara_helpers.rb b/spec/support/capybara_helpers.rb
index 9b5c3065eed..b57a3493aff 100644
--- a/spec/support/capybara_helpers.rb
+++ b/spec/support/capybara_helpers.rb
@@ -27,6 +27,14 @@ module CapybaraHelpers
end
end
end
+
+ # Refresh the page. Calling `visit current_url` doesn't seem to work consistently.
+ #
+ def refresh
+ url = current_url
+ visit 'about:blank'
+ visit url
+ end
end
RSpec.configure do |config|
diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb
index 9f9ef20f99b..bb6c84262f6 100644
--- a/spec/support/test_env.rb
+++ b/spec/support/test_env.rb
@@ -5,19 +5,20 @@ module TestEnv
# When developing the seed repository, comment out the branch you will modify.
BRANCH_SHA = {
- 'empty-branch' => '7efb185',
- 'flatten-dir' => 'e56497b',
- 'feature' => '0b4bc9a',
- 'feature_conflict' => 'bb5206f',
- 'fix' => '48f0be4',
- 'improve/awesome' => '5937ac0',
- 'markdown' => '0ed8c6c',
- 'lfs' => 'be93687',
- 'master' => '5937ac0',
- "'test'" => 'e56497b',
- 'orphaned-branch' => '45127a9',
- 'binary-encoding' => '7b1cf43',
- 'gitattributes' => '5a62481',
+ 'empty-branch' => '7efb185',
+ 'flatten-dir' => 'e56497b',
+ 'feature' => '0b4bc9a',
+ 'feature_conflict' => 'bb5206f',
+ 'fix' => '48f0be4',
+ 'improve/awesome' => '5937ac0',
+ 'markdown' => '0ed8c6c',
+ 'lfs' => 'be93687',
+ 'master' => '5937ac0',
+ "'test'" => 'e56497b',
+ 'orphaned-branch' => '45127a9',
+ 'binary-encoding' => '7b1cf43',
+ 'gitattributes' => '5a62481',
+ 'expand-collapse-diffs' => '4842455'
}
# gitlab-test-fork is a fork of gitlab-fork, but we don't necessarily
@@ -63,7 +64,7 @@ module TestEnv
end
def disable_pre_receive
- allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return(true)
+ allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([true, nil])
end
# Clean /tmp/tests
diff --git a/spec/workers/git_garbage_collect_worker_spec.rb b/spec/workers/git_garbage_collect_worker_spec.rb
new file mode 100644
index 00000000000..a9cce8b8b59
--- /dev/null
+++ b/spec/workers/git_garbage_collect_worker_spec.rb
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe GitGarbageCollectWorker do
+ let(:project) { create(:project) }
+ let(:shell) { Gitlab::Shell.new }
+
+ subject { GitGarbageCollectWorker.new }
+
+ before do
+ allow(subject).to receive(:gitlab_shell).and_return(shell)
+ end
+
+ describe "#perform" do
+ it "runs `git gc`" do
+ expect(shell).to receive(:gc).with(
+ project.repository_storage_path,
+ project.path_with_namespace).
+ and_return(true)
+ expect_any_instance_of(Repository).to receive(:after_create_branch)
+
+ subject.perform(project.id)
+ end
+ end
+end
diff --git a/vendor/gitignore/Android.gitignore b/vendor/gitignore/Android.gitignore
index f6b286cea98..e5df7b9150e 100644
--- a/vendor/gitignore/Android.gitignore
+++ b/vendor/gitignore/Android.gitignore
@@ -35,6 +35,7 @@ captures/
# Intellij
*.iml
.idea/workspace.xml
+.idea/libraries
# Keystore files
*.jks
diff --git a/vendor/gitignore/C++.gitignore b/vendor/gitignore/C++.gitignore
index 4581ef2eeef..259148fa18f 100644
--- a/vendor/gitignore/C++.gitignore
+++ b/vendor/gitignore/C++.gitignore
@@ -1,3 +1,6 @@
+# Prerequisites
+*.d
+
# Compiled Object files
*.slo
*.lo
diff --git a/vendor/gitignore/C.gitignore b/vendor/gitignore/C.gitignore
index f805e810e5c..7a065c709c7 100644
--- a/vendor/gitignore/C.gitignore
+++ b/vendor/gitignore/C.gitignore
@@ -1,3 +1,6 @@
+# Prerequisites
+*.d
+
# Object files
*.o
*.ko
diff --git a/vendor/gitignore/Gradle.gitignore b/vendor/gitignore/Gradle.gitignore
index 77617a15c38..a1fc39c070f 100644
--- a/vendor/gitignore/Gradle.gitignore
+++ b/vendor/gitignore/Gradle.gitignore
@@ -1,5 +1,5 @@
.gradle
-build/
+/build/
# Ignore Gradle GUI config
gradle-app.setting
diff --git a/vendor/gitignore/LICENSE b/vendor/gitignore/LICENSE
index b8a103ac9b1..0e259d42c99 100644
--- a/vendor/gitignore/LICENSE
+++ b/vendor/gitignore/LICENSE
@@ -1,19 +1,121 @@
-Copyright (c) 2016 GitHub, Inc.
-
-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.
+Creative Commons Legal Code
+
+CC0 1.0 Universal
+
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
+ HEREUNDER.
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work of
+authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without fear
+of later claims of infringement build upon, modify, incorporate in other
+works, reuse and redistribute as freely as possible in any form whatsoever
+and for any purposes, including without limitation commercial purposes.
+These owners may contribute to the Commons to promote the ideal of a free
+culture and the further production of creative, cultural and scientific
+works, or to gain reputation or greater distribution for their Work in
+part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or she
+is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under its
+terms, with knowledge of his or her Copyright and Related Rights in the
+Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+protected by copyright and related or neighboring rights ("Copyright and
+Related Rights"). Copyright and Related Rights include, but are not
+limited to, the following:
+
+ i. the right to reproduce, adapt, distribute, perform, display,
+ communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or performer(s);
+iii. publicity and privacy rights pertaining to a person's image or
+ likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a Work,
+ subject to the limitations in paragraph 4(a), below;
+ v. rights protecting the extraction, dissemination, use and reuse of data
+ in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC of the
+ European Parliament and of the Council of 11 March 1996 on the legal
+ protection of databases, and under any national implementation
+ thereof, including any amended or successor version of such
+ directive); and
+vii. other similar, equivalent or corresponding rights throughout the
+ world based on applicable law or treaty, and any national
+ implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention
+of, applicable law, Affirmer hereby overtly, fully, permanently,
+irrevocably and unconditionally waives, abandons, and surrenders all of
+Affirmer's Copyright and Related Rights and associated claims and causes
+of action, whether now known or unknown (including existing as well as
+future claims and causes of action), in the Work (i) in all territories
+worldwide, (ii) for the maximum duration provided by applicable law or
+treaty (including future time extensions), (iii) in any current or future
+medium and for any number of copies, and (iv) for any purpose whatsoever,
+including without limitation commercial, advertising or promotional
+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
+member of the public at large and to the detriment of Affirmer's heirs and
+successors, fully intending that such Waiver shall not be subject to
+revocation, rescission, cancellation, termination, or any other legal or
+equitable action to disrupt the quiet enjoyment of the Work by the public
+as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason
+be judged legally invalid or ineffective under applicable law, then the
+Waiver shall be preserved to the maximum extent permitted taking into
+account Affirmer's express Statement of Purpose. In addition, to the
+extent the Waiver is so judged Affirmer hereby grants to each affected
+person a royalty-free, non transferable, non sublicensable, non exclusive,
+irrevocable and unconditional license to exercise Affirmer's Copyright and
+Related Rights in the Work (i) in all territories worldwide, (ii) for the
+maximum duration provided by applicable law or treaty (including future
+time extensions), (iii) in any current or future medium and for any number
+of copies, and (iv) for any purpose whatsoever, including without
+limitation commercial, advertising or promotional purposes (the
+"License"). The License shall be deemed effective as of the date CC0 was
+applied by Affirmer to the Work. Should any part of the License for any
+reason be judged legally invalid or ineffective under applicable law, such
+partial invalidity or ineffectiveness shall not invalidate the remainder
+of the License, and in such case Affirmer hereby affirms that he or she
+will not (i) exercise any of his or her remaining Copyright and Related
+Rights in the Work or (ii) assert any associated claims and causes of
+action with respect to the Work, in either case contrary to Affirmer's
+express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
+ surrendered, licensed or otherwise affected by this document.
+ b. Affirmer offers the Work as-is and makes no representations or
+ warranties of any kind concerning the Work, express, implied,
+ statutory or otherwise, including without limitation warranties of
+ title, merchantability, fitness for a particular purpose, non
+ infringement, or the absence of latent or other defects, accuracy, or
+ the present or absence of errors, whether or not discoverable, all to
+ the greatest extent permissible under applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other persons
+ that may apply to the Work or any use thereof, including without
+ limitation any person's Copyright and Related Rights in the Work.
+ Further, Affirmer disclaims responsibility for obtaining any necessary
+ consents, permissions or other rights required for any use of the
+ Work.
+ d. Affirmer understands and acknowledges that Creative Commons is not a
+ party to this document and has no duty or obligation with respect to
+ this CC0 or use of the Work.
diff --git a/vendor/gitignore/Node.gitignore b/vendor/gitignore/Node.gitignore
index 5148e527a7e..aea5294de9d 100644
--- a/vendor/gitignore/Node.gitignore
+++ b/vendor/gitignore/Node.gitignore
@@ -7,6 +7,7 @@ npm-debug.log*
pids
*.pid
*.seed
+*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
diff --git a/vendor/gitignore/TeX.gitignore b/vendor/gitignore/TeX.gitignore
index 4123a577c47..3cb097c9d5e 100644
--- a/vendor/gitignore/TeX.gitignore
+++ b/vendor/gitignore/TeX.gitignore
@@ -152,6 +152,9 @@ pythontex-files-*/
# todonotes
*.tdo
+# easy-todo
+*.lod
+
# xindy
*.xdy
diff --git a/vendor/gitlab-ci-yml/Maven.gitlab-ci.yml b/vendor/gitlab-ci-yml/Maven.gitlab-ci.yml
new file mode 100644
index 00000000000..1678a47f9ac
--- /dev/null
+++ b/vendor/gitlab-ci-yml/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.
+# * Does only verify merge requests but deploy built artifacts of the
+# master branch.
+# * 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: "-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.
+cache:
+ paths:
+ - /root/.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/Pages/brunch.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Brunch.gitlab-ci.yml
index 7fcc0b436b5..7fcc0b436b5 100644
--- a/vendor/gitlab-ci-yml/Pages/brunch.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Brunch.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/doxygen.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Doxygen.gitlab-ci.yml
index 791afdd23f1..791afdd23f1 100644
--- a/vendor/gitlab-ci-yml/Pages/doxygen.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Doxygen.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/html.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/HTML.gitlab-ci.yml
index 249a168aa33..249a168aa33 100644
--- a/vendor/gitlab-ci-yml/Pages/html.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/HTML.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/harp.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Harp.gitlab-ci.yml
index dd3ef149668..dd3ef149668 100644
--- a/vendor/gitlab-ci-yml/Pages/harp.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Harp.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/hexo.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Hexo.gitlab-ci.yml
index b468d79bcad..b468d79bcad 100644
--- a/vendor/gitlab-ci-yml/Pages/hexo.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Hexo.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/hugo.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Hugo.gitlab-ci.yml
index 45df6975259..45df6975259 100644
--- a/vendor/gitlab-ci-yml/Pages/hugo.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Hugo.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/hyde.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Hyde.gitlab-ci.yml
index f5b40f2b9f1..f5b40f2b9f1 100644
--- a/vendor/gitlab-ci-yml/Pages/hyde.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Hyde.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/jekyll.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Jekyll.gitlab-ci.yml
index 36918fc005a..36918fc005a 100644
--- a/vendor/gitlab-ci-yml/Pages/jekyll.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Jekyll.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/lektor.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Lektor.gitlab-ci.yml
index c5c44a5d86c..c5c44a5d86c 100644
--- a/vendor/gitlab-ci-yml/Pages/lektor.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Lektor.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/metalsmith.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Metalsmith.gitlab-ci.yml
index 50e8b7ccd46..50e8b7ccd46 100644
--- a/vendor/gitlab-ci-yml/Pages/metalsmith.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Metalsmith.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/middleman.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Middleman.gitlab-ci.yml
index 9f4cc0574d6..9f4cc0574d6 100644
--- a/vendor/gitlab-ci-yml/Pages/middleman.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Middleman.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/nanoc.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Nanoc.gitlab-ci.yml
index b469b316ba5..b469b316ba5 100644
--- a/vendor/gitlab-ci-yml/Pages/nanoc.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Nanoc.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/octopress.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Octopress.gitlab-ci.yml
index 4762ec9acfd..4762ec9acfd 100644
--- a/vendor/gitlab-ci-yml/Pages/octopress.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Octopress.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/pelican.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Pelican.gitlab-ci.yml
index c5f3154f587..c5f3154f587 100644
--- a/vendor/gitlab-ci-yml/Pages/pelican.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Pelican.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml b/vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml
index 78f3e39949f..2a761bbd127 100644
--- a/vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml
@@ -10,12 +10,19 @@ services:
- redis:latest
- postgres:latest
+# Cache gems in between builds
+cache:
+ paths:
+ - vendor/ruby
+
# This is a basic example for a gem or script which doesn't use
# services such as redis or postgres
before_script:
- - gem install bundler # Bundler is not installed with the image
- - bundle install -j $(nproc) # Install dependencies
+ - ruby -v # Print out ruby version for debugging
+ - gem install bundler --no-ri --no-rdoc # Bundler is not installed with the image
+ - bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby
+# Optional - Delete if not using `rubocop`
rubocop:
script:
- rubocop
@@ -26,5 +33,5 @@ rspec:
rails:
script:
- - rake db:migrate
- - rspec spec
+ - bundle exec rake db:migrate
+ - bundle exec rake test
diff --git a/vendor/gitlab-ci-yml/Rust.gitlab-ci.yml b/vendor/gitlab-ci-yml/Rust.gitlab-ci.yml
new file mode 100644
index 00000000000..ae3f7405ea3
--- /dev/null
+++ b/vendor/gitlab-ci-yml/Rust.gitlab-ci.yml
@@ -0,0 +1,23 @@
+# Unofficial language image. Look for the different tagged releases at:
+# https://hub.docker.com/r/scorpil/rust/tags/
+image: "scorpil/rust:stable"
+
+# Optional: 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-service
+#services:
+# - mysql:latest
+# - redis:latest
+# - postgres:latest
+
+# Optional: Install a C compiler, cmake and git into the container.
+# You will often need this when you (or any of your dependencies) depends on C code.
+#before_script:
+#- apt-get update -yqq
+#- apt-get install -yqq --no-install-recommends build-essential
+
+# Use cargo to test the project
+test:cargo:
+ script:
+ - rustc --version && cargo --version # Print version info for debugging
+ - cargo test --verbose --jobs 1 --release # Don't paralize to make errors more readable
diff --git a/vendor/gitlab-ci-yml/Scala.gitlab-ci.yml b/vendor/gitlab-ci-yml/Scala.gitlab-ci.yml
new file mode 100644
index 00000000000..443ba42e38c
--- /dev/null
+++ b/vendor/gitlab-ci-yml/Scala.gitlab-ci.yml
@@ -0,0 +1,22 @@
+# Official Java image. Look for the different tagged releases at
+# https://hub.docker.com/r/library/java/tags/ . A Java image is not required
+# but an image with a JVM speeds up the build a bit.
+image: java:8
+
+before_script:
+ # Enable the usage of sources over https
+ - apt-get update -yqq
+ - apt-get install apt-transport-https -yqq
+ # Add keyserver for SBT
+ - echo "deb http://dl.bintray.com/sbt/debian /" | tee -a /etc/apt/sources.list.d/sbt.list
+ - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 642AC823
+ # Install SBT
+ - apt-get update -yqq
+ - apt-get install sbt -yqq
+ # Log the sbt version
+ - sbt sbt-version
+
+test:
+ script:
+ # Execute your project's tests
+ - sbt clean test