Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-07-08 09:09:44 +00:00
parent 24fa0480c0
commit 058e1a233f
23 changed files with 218 additions and 55 deletions

View File

@ -20,7 +20,7 @@ export default {
hide(this.$refs.toggleFocusModeButton);
const issueBoardsContent = document.querySelector('.content-wrapper > .js-focus-mode-board');
issueBoardsContent.classList.toggle('is-focused');
issueBoardsContent?.classList.toggle('is-focused');
this.isFullscreen = !this.isFullscreen;
},

View File

@ -1,4 +1,5 @@
import Vue from 'vue';
import Vuex from 'vuex';
import VueApollo from 'vue-apollo';
import PipelineTabs from 'ee_else_ce/pipelines/components/pipeline_tabs.vue';
import { removeParams, updateHistory } from '~/lib/utils/url_utility';
@ -7,6 +8,7 @@ import { parseBoolean } from '~/lib/utils/common_utils';
import { getPipelineDefaultTab, reportToSentry } from './utils';
Vue.use(VueApollo);
Vue.use(Vuex);
export const createAppOptions = (selector, apolloProvider) => {
const el = document.querySelector(selector);
@ -37,6 +39,7 @@ export const createAppOptions = (selector, apolloProvider) => {
PipelineTabs,
},
apolloProvider,
store: new Vuex.Store(),
provide: {
canGenerateCodequalityReports: parseBoolean(canGenerateCodequalityReports),
codequalityReportDownloadPath,

View File

@ -176,11 +176,16 @@
}
.gutter-toggle {
display: flex;
align-items: center;
margin-left: 20px;
padding-left: 10px;
padding: 4px;
border-radius: 4px;
height: 24px;
&:hover {
color: $gl-text-color;
background: $gray-50;
}
&:hover,
@ -338,7 +343,6 @@
}
.gutter-toggle {
border-left: 1px solid $border-gray-normal;
text-align: center;
}
@ -405,8 +409,8 @@
width: 100%;
height: $sidebar-toggle-height;
margin-left: 0;
padding-left: 0;
border-bottom: 1px solid $border-white-normal;
border-radius: 0;
}
a.gutter-toggle {

View File

@ -2,6 +2,9 @@
// Please see the feedback issue for more details and help:
// https://gitlab.com/gitlab-org/gitlab/-/issues/331812
@charset "UTF-8";
:root {
color-scheme: dark;
}
body.gl-dark {
--gray-10: #1f1f1f;
--gray-50: #303030;
@ -1714,6 +1717,9 @@ svg.s16 {
.rect-avatar.s32 {
border-radius: 4px;
}
:root {
color-scheme: dark;
}
body.gl-dark {
--gray-10: #1f1f1f;
--gray-50: #303030;
@ -1955,6 +1961,9 @@ body.gl-dark .navbar-gitlab .search form .search-input {
color: var(--gl-text-color);
}
:root {
color-scheme: dark;
}
body.gl-dark {
--gray-10: #1f1f1f;
--gray-50: #303030;

View File

@ -101,6 +101,10 @@ $white-dark: #444;
$border-color: #4f4f4f;
$nav-active-bg: rgba(255, 255, 255, 0.08);
:root {
color-scheme: dark;
}
body.gl-dark {
--gray-10: #{$gray-10};
--gray-50: #{$gray-50};

View File

@ -4,7 +4,7 @@ module Projects
module PipelineHelper
extend ::Ci::BuildsHelper
def js_pipeline_tabs_data(project, pipeline)
def js_pipeline_tabs_data(project, pipeline, _user)
{
can_generate_codequality_reports: pipeline.can_generate_codequality_reports?.to_json,
failed_jobs_count: pipeline.failed_builds.count,

View File

@ -1572,6 +1572,10 @@ class User < ApplicationRecord
self.followees.exists?(user.id)
end
def followed_by?(user)
self.followers.include?(user)
end
def follow(user)
return false if self.id == user.id

View File

@ -27,7 +27,7 @@
= s_('You can also test your %{gitlab_ci_yml} in %{lint_link_start}CI Lint%{lint_link_end}').html_safe % { gitlab_ci_yml: '.gitlab-ci.yml', lint_link_start: lint_link_start, lint_link_end: '</a>'.html_safe }
- if Feature.enabled?(:pipeline_tabs_vue, @project)
#js-pipeline-tabs{ data: js_pipeline_tabs_data(@project, @pipeline) }
#js-pipeline-tabs{ data: js_pipeline_tabs_data(@project, @pipeline, @current_user) }
- else
= render "projects/pipelines/with_tabs", pipeline: @pipeline, stages: @stages, pipeline_has_errors: pipeline_has_errors
.js-pipeline-details-vue{ data: { metrics_path: namespace_project_ci_prometheus_metrics_histograms_path(namespace_id: @project.namespace, project_id: @project, format: :json), pipeline_project_path: @project.full_path, pipeline_iid: @pipeline.iid, graphql_resource_etag: graphql_etag_pipeline_path(@pipeline) } }

View File

@ -96,7 +96,7 @@ Our criteria for the separation of duties is as follows:
The Chain of Custody report allows customers to export a list of merge commits within the group.
The data provides a comprehensive view with respect to merge commits. It includes the merge commit SHA,
merge request author, merge request ID, merge user, pipeline ID, group name, project name, and merge request approvers.
merge request author, merge request ID, merge user, date merged, pipeline ID, group name, project name, and merge request approvers.
Depending on the merge strategy, the merge commit SHA can be a merge commit, squash commit, or a diff head commit.
To download the Chain of Custody report:

View File

@ -19,7 +19,7 @@ module API
user.followees.size
end
expose :is_followed, if: ->(user, opts) { Ability.allowed?(opts[:current_user], :read_user_profile, user) && opts[:current_user] } do |user, opts|
opts[:current_user].following?(user)
user.followed_by?(opts[:current_user])
end
expose :local_time do |user|
local_time(user.timezone)

View File

@ -125,7 +125,7 @@ module API
entity = current_user&.admin? ? Entities::UserWithAdmin : Entities::UserBasic
if entity == Entities::UserWithAdmin
users = users.preload(:identities, :u2f_registrations, :webauthn_registrations, :namespace)
users = users.preload(:identities, :u2f_registrations, :webauthn_registrations, :namespace, :followers, :followees, :user_preference)
end
users, options = with_custom_attributes(users, { with: entity, current_user: current_user })

View File

@ -800,9 +800,9 @@ module Gitlab
end
end
def list_refs
def list_refs(patterns = [Gitlab::Git::BRANCH_REF_PREFIX])
wrapped_gitaly_errors do
gitaly_ref_client.list_refs
gitaly_ref_client.list_refs(patterns)
end
end

View File

@ -41023,6 +41023,9 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
msgid "Unable to parse the vulnerability report's options."
msgstr ""
msgid "Unable to save iteration. Please try again"
msgstr ""

View File

@ -0,0 +1,59 @@
import Vuex from 'vuex';
import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
import ConfigToggle from '~/boards/components/config_toggle.vue';
import eventHub from '~/boards/eventhub';
import store from '~/boards/stores';
import { mockTracking } from 'helpers/tracking_helper';
describe('ConfigToggle', () => {
let wrapper;
Vue.use(Vuex);
const createComponent = (provide = {}) =>
shallowMount(ConfigToggle, {
store,
provide: {
canAdminList: true,
...provide,
},
});
const findButton = () => wrapper.findComponent(GlButton);
afterEach(() => {
wrapper.destroy();
});
it('renders a button with label `View scope` when `canAdminList` is `false`', () => {
wrapper = createComponent({ canAdminList: false });
expect(findButton().text()).toBe('View scope');
});
it('renders a button with label `Edit board` when `canAdminList` is `true`', () => {
wrapper = createComponent();
expect(findButton().text()).toBe('Edit board');
});
it('emits `showBoardModal` when button is clicked', () => {
const eventHubSpy = jest.spyOn(eventHub, '$emit');
wrapper = createComponent();
findButton().vm.$emit('click', { preventDefault: () => {} });
expect(eventHubSpy).toHaveBeenCalledWith('showBoardModal', 'edit');
});
it('tracks clicking the button', () => {
const trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
wrapper = createComponent();
findButton().vm.$emit('click', { preventDefault: () => {} });
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_button', {
label: 'edit_board',
});
});
});

View File

@ -0,0 +1,47 @@
import { GlButton } from '@gitlab/ui';
import { nextTick } from 'vue';
import ToggleFocus from '~/boards/components/toggle_focus.vue';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
describe('ToggleFocus', () => {
let wrapper;
const createComponent = () => {
wrapper = shallowMountExtended(ToggleFocus, {
directives: {
GlTooltip: createMockDirective(),
},
attachTo: document.body,
});
};
const findButton = () => wrapper.findComponent(GlButton);
afterEach(() => {
wrapper.destroy();
});
it('renders a button with `maximize` icon', () => {
createComponent();
expect(findButton().props('icon')).toBe('maximize');
expect(findButton().attributes('aria-label')).toBe(ToggleFocus.i18n.toggleFocusMode);
});
it('contains a tooltip with title', () => {
createComponent();
const tooltip = getBinding(findButton().element, 'gl-tooltip');
expect(tooltip).toBeDefined();
expect(findButton().attributes('title')).toBe(ToggleFocus.i18n.toggleFocusMode);
});
it('toggles the icon when the button is clicked', async () => {
createComponent();
findButton().vm.$emit('click');
await nextTick();
expect(findButton().props('icon')).toBe('minimize');
});
});

View File

@ -11,7 +11,11 @@ RSpec.describe Projects::PipelineHelper do
let_it_be(:pipeline) { Ci::PipelinePresenter.new(raw_pipeline, current_user: user)}
describe '#js_pipeline_tabs_data' do
subject(:pipeline_tabs_data) { helper.js_pipeline_tabs_data(project, pipeline) }
before do
project.add_developer(user)
end
subject(:pipeline_tabs_data) { helper.js_pipeline_tabs_data(project, pipeline, user) }
it 'returns pipeline tabs data' do
expect(pipeline_tabs_data).to include({

View File

@ -367,8 +367,8 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
end
it 'returns the correct count bounding at max_count' do
branch_a_sha = repository_rugged.branches['left-branch'].target.oid
branch_b_sha = repository_rugged.branches['right-branch'].target.oid
branch_a_sha = repository.find_branch('left-branch').dereferenced_target.sha
branch_b_sha = repository.find_branch('right-branch').dereferenced_target.sha
count = repository.diverging_commit_count(branch_a_sha, branch_b_sha, max_count: 1000)
@ -407,8 +407,8 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
end
it 'returns the correct count bounding at max_count' do
branch_a_sha = repository_rugged.branches['left-branch'].target.oid
branch_b_sha = repository_rugged.branches['right-branch'].target.oid
branch_a_sha = repository.find_branch('left-branch').dereferenced_target.sha
branch_b_sha = repository.find_branch('right-branch').dereferenced_target.sha
results = repository.diverging_commit_count(branch_a_sha, branch_b_sha, max_count: max_count)
@ -469,16 +469,14 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
it 'deletes the ref' do
repository.delete_refs('refs/heads/feature')
expect(repository_rugged.references['refs/heads/feature']).to be_nil
expect(repository.find_branch('feature')).to be_nil
end
it 'deletes all refs' do
refs = %w[refs/heads/wip refs/tags/v1.1.0]
repository.delete_refs(*refs)
refs.each do |ref|
expect(repository_rugged.references[ref]).to be_nil
end
expect(repository.list_refs(refs)).to be_empty
end
it 'does not fail when deleting an empty list of refs' do
@ -491,7 +489,7 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
end
describe '#branch_names_contains_sha' do
let(:head_id) { repository_rugged.head.target.oid }
let(:head_id) { repository.commit.id }
let(:new_branch) { head_id }
let(:utf8_branch) { 'branch-é' }
@ -1823,7 +1821,7 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
let(:new_oid) { new_commit_edit_old_file(source_rugged).oid }
before do
source_rugged.branches.create(source_branch, new_oid)
source_repository.write_ref(source_branch, new_oid)
end
it 'writes the ref' do
@ -1869,7 +1867,7 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
it "removes the branch from the repo" do
repository.rm_branch(branch_name, user: user)
expect(repository_rugged.branches[branch_name]).to be_nil
expect(repository.find_branch(branch_name)).to be_nil
end
end
@ -2342,16 +2340,10 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
end
def create_remote_branch(remote_name, branch_name, source_branch_name)
source_branch = repository.branches.find { |branch| branch.name == source_branch_name }
source_branch = repository.find_branch(source_branch_name)
repository.write_ref("refs/remotes/#{remote_name}/#{branch_name}", source_branch.dereferenced_target.sha)
end
def refs(dir)
IO.popen(%W[git -C #{dir} for-each-ref], &:read).split("\n").map do |line|
line.split("\t").last
end
end
describe '#disconnect_alternates' do
let(:project) { create(:project, :repository) }
let(:pool_repository) { create(:pool_repository) }
@ -2483,7 +2475,7 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
it 'mirrors the source repository' do
subject
expect(refs(new_repository_path)).to eq(refs(repository_path))
expect(new_repository.list_refs(['refs/'])).to eq(repository.list_refs(['refs/']))
end
end
@ -2495,7 +2487,7 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
it 'mirrors the source repository' do
subject
expect(refs(new_repository_path)).to eq(refs(repository_path))
expect(new_repository.list_refs(['refs/'])).to eq(repository.list_refs(['refs/']))
end
context 'with keep-around refs' do
@ -2511,8 +2503,8 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
it 'includes the temporary and keep-around refs' do
subject
expect(refs(new_repository_path)).to include(keep_around_ref)
expect(refs(new_repository_path)).to include(tmp_ref)
expect(new_repository.list_refs([keep_around_ref]).map(&:name)).to match_array([keep_around_ref])
expect(new_repository.list_refs([tmp_ref]).map(&:name)).to match_array([tmp_ref])
end
end
end

View File

@ -2259,20 +2259,12 @@ RSpec.describe Repository do
describe '#branch_count' do
it 'returns the number of branches' do
expect(repository.branch_count).to be_an(Integer)
rugged_count = rugged_repo(repository).branches.count
expect(repository.branch_count).to eq(rugged_count)
end
end
describe '#tag_count' do
it 'returns the number of tags' do
expect(repository.tag_count).to be_an(Integer)
rugged_count = rugged_repo(repository).tags.count
expect(repository.tag_count).to eq(rugged_count)
end
end

View File

@ -3442,6 +3442,15 @@ RSpec.describe User do
end
end
describe '#followed_by?' do
it 'check if followed by another user' do
follower = create :user
followee = create :user
expect { follower.follow(followee) }.to change { followee.followed_by?(follower) }.from(false).to(true)
end
end
describe '#follow' do
it 'follow another user' do
user = create :user

View File

@ -185,6 +185,40 @@ RSpec.describe API::Users do
expect(json_response.first['note']).to eq '2018-11-05 | 2FA removed | user requested | www.gitlab.com'
end
end
context 'N+1 queries' do
before do
create_list(:user, 2)
end
it 'avoids N+1 queries when requested by admin' do
control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
get api("/users", admin)
end.count
create_list(:user, 3)
# There is a still a pending N+1 query related to fetching
# project count for each user.
# Refer issue https://gitlab.com/gitlab-org/gitlab/-/issues/367080
expect do
get api("/users", admin)
end.not_to exceed_all_query_limit(control_count + 3)
end
it 'avoids N+1 queries when requested by a regular user' do
control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
get api("/users", user)
end.count
create_list(:user, 3)
expect do
get api("/users", user)
end.not_to exceed_all_query_limit(control_count)
end
end
end
end

View File

@ -39,8 +39,7 @@ RSpec.describe Projects::AfterImportWorker do
end
it 'removes refs/pull/**/*' do
expect(rugged.references.map(&:name))
.not_to include(%r{\Arefs/pull/})
expect(repository.list_refs(['refs/pull/'])).to be_empty
end
end
@ -53,8 +52,7 @@ RSpec.describe Projects::AfterImportWorker do
end
it "does not remove refs/#{name}/tmp" do
expect(rugged.references.map(&:name))
.to include("refs/#{name}/tmp")
expect(repository.list_refs(["refs/#{name}/tmp"]).length).to be(1)
end
end
end
@ -100,8 +98,7 @@ RSpec.describe Projects::AfterImportWorker do
it 'removes refs/pull/**/*' do
subject
expect(rugged.references.map(&:name))
.not_to include(%r{\Arefs/pull/})
expect(repository.list_refs(['refs/pull/'])).to be_empty
end
it 'records the failures in the database', :aggregate_failures do
@ -123,9 +120,5 @@ RSpec.describe Projects::AfterImportWorker do
expect(import_failure.correlation_id_value).not_to be_empty
end
end
def rugged
rugged_repo(repository)
end
end
end

View File

@ -36,7 +36,7 @@ require (
golang.org/x/tools v0.1.11
google.golang.org/grpc v1.45.0
google.golang.org/protobuf v1.28.0
honnef.co/go/tools v0.1.3
honnef.co/go/tools v0.3.2
)
require (
@ -102,6 +102,7 @@ require (
go.opencensus.io v0.23.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a // indirect
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect

View File

@ -144,6 +144,7 @@ github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
@ -1211,7 +1212,10 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5 h1:FR+oGxGfbQu1d+jglI3rCkjAjUnhRSZcUxr+DqlDLNo=
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e h1:qyrTQ++p1afMkO4DPEeLGq/3oTsdlvdH4vqZUBWzUKM=
golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@ -1555,6 +1559,7 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.11-0.20220513221640-090b14e8501f/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
golang.org/x/tools v0.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY=
golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -1830,8 +1835,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.1.3 h1:qTakTkI6ni6LFD5sBwwsdSO+AQqbSIxOauHTTQKZ/7o=
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
honnef.co/go/tools v0.3.2 h1:ytYb4rOqyp1TSa2EPvNVwtPQJctSELKaMyLfqNP4+34=
honnef.co/go/tools v0.3.2/go.mod h1:jzwdWgg7Jdq75wlfblQxO4neNaFFSvgc1tD5Wv8U0Yw=
nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=