Merge pull request 'move master to main' (#1) from master into main
Reviewed-on: erius/itmo-go#1
This commit is contained in:
commit
83f0d33374
269 changed files with 5275 additions and 1624 deletions
190
.deadlines.yml
190
.deadlines.yml
|
@ -1,190 +0,0 @@
|
||||||
- group: Bonus
|
|
||||||
start: 11-02-2023 18:00
|
|
||||||
deadline: 29-05-2023 23:59
|
|
||||||
tasks:
|
|
||||||
- task: consistenthash
|
|
||||||
score: 200
|
|
||||||
- task: gossip
|
|
||||||
score: 300
|
|
||||||
- task: smartsched
|
|
||||||
score: 200
|
|
||||||
watch:
|
|
||||||
- distbuild/pkg/scheduler
|
|
||||||
- task: wasm
|
|
||||||
score: 300
|
|
||||||
|
|
||||||
- group: Analysis
|
|
||||||
start: 29-04-2023 18:00
|
|
||||||
deadline: 10-05-2023 23:59
|
|
||||||
tasks:
|
|
||||||
- task: testifycheck
|
|
||||||
score: 200
|
|
||||||
- task: gzep
|
|
||||||
score: 100
|
|
||||||
|
|
||||||
- group: "[HW] Dist Build"
|
|
||||||
start: 26-04-2023 12:00
|
|
||||||
deadline: 29-05-2023 23:59
|
|
||||||
tasks:
|
|
||||||
- task: distbuild
|
|
||||||
score: 0
|
|
||||||
|
|
||||||
- group: Low level
|
|
||||||
start: 22-04-2023 16:00
|
|
||||||
deadline: 03-05-2023 23:59
|
|
||||||
tasks:
|
|
||||||
- task: illegal
|
|
||||||
score: 100
|
|
||||||
- task: blowfish
|
|
||||||
score: 100
|
|
||||||
|
|
||||||
- group: Reflect
|
|
||||||
start: 15-04-2023 16:00
|
|
||||||
deadline: 25-04-2023 23:59
|
|
||||||
tasks:
|
|
||||||
- task: reversemap
|
|
||||||
score: 100
|
|
||||||
- task: jsonlist
|
|
||||||
score: 100
|
|
||||||
- task: jsonrpc
|
|
||||||
score: 100
|
|
||||||
- task: structtags
|
|
||||||
score: 100
|
|
||||||
|
|
||||||
- group: SQL
|
|
||||||
start: 08-04-2023 16:00
|
|
||||||
deadline: 18-04-2023 23:59
|
|
||||||
tasks:
|
|
||||||
- task: dao
|
|
||||||
score: 100
|
|
||||||
- task: ledger
|
|
||||||
score: 200
|
|
||||||
- task: shopfront
|
|
||||||
score: 100
|
|
||||||
- task: wscat
|
|
||||||
score: 200
|
|
||||||
|
|
||||||
- group: Generics
|
|
||||||
start: 01-04-2023 16:00
|
|
||||||
deadline: 11-04-2023 23:59
|
|
||||||
tasks:
|
|
||||||
- task: genericsum
|
|
||||||
score: 100
|
|
||||||
- task: treeiter
|
|
||||||
score: 100
|
|
||||||
- task: coverme
|
|
||||||
score: 300
|
|
||||||
|
|
||||||
- group: HTTP
|
|
||||||
start: 25-03-2023 16:00
|
|
||||||
deadline: 06-04-2023 23:59
|
|
||||||
tasks:
|
|
||||||
- task: urlshortener
|
|
||||||
score: 100
|
|
||||||
- task: digitalclock
|
|
||||||
score: 100
|
|
||||||
- task: middleware
|
|
||||||
score: 200
|
|
||||||
- task: olympics
|
|
||||||
score: 200
|
|
||||||
- task: firewall
|
|
||||||
score: 200
|
|
||||||
|
|
||||||
- group: Concurrency with shared memory
|
|
||||||
start: 18-03-2023 15:59
|
|
||||||
deadline: 29-03-2023 23:59
|
|
||||||
tasks:
|
|
||||||
- task: dupcall
|
|
||||||
score: 200
|
|
||||||
- task: keylock
|
|
||||||
score: 200
|
|
||||||
- task: batcher
|
|
||||||
score: 200
|
|
||||||
- task: pubsub
|
|
||||||
score: 300
|
|
||||||
|
|
||||||
- group: Testing
|
|
||||||
start: 11-03-2023 13:00
|
|
||||||
deadline: 21-03-2023 23:59
|
|
||||||
tasks:
|
|
||||||
- task: testequal
|
|
||||||
score: 100
|
|
||||||
- task: fileleak
|
|
||||||
score: 100
|
|
||||||
- task: tabletest
|
|
||||||
score: 100
|
|
||||||
- task: tparallel
|
|
||||||
score: 200
|
|
||||||
- task: iprange
|
|
||||||
score: 100
|
|
||||||
|
|
||||||
- group: "[HW] Gitfame"
|
|
||||||
start: 04-03-2023 16:30
|
|
||||||
deadline: 19-03-2023 23:59
|
|
||||||
tasks:
|
|
||||||
- task: gitfame
|
|
||||||
score: 0
|
|
||||||
|
|
||||||
- group: Goroutines
|
|
||||||
start: 04-03-2023 16:30
|
|
||||||
deadline: 14-03-2023 23:59
|
|
||||||
tasks:
|
|
||||||
- task: tour1
|
|
||||||
score: 100
|
|
||||||
- task: once
|
|
||||||
score: 100
|
|
||||||
- task: rwmutex
|
|
||||||
score: 100
|
|
||||||
- task: waitgroup
|
|
||||||
score: 100
|
|
||||||
- task: cond
|
|
||||||
score: 100
|
|
||||||
- task: ratelimit
|
|
||||||
score: 100
|
|
||||||
|
|
||||||
- group: Interfaces
|
|
||||||
start: 25-02-2023 16:30
|
|
||||||
deadline: 07-03-2023 23:59
|
|
||||||
tasks:
|
|
||||||
- task: otp
|
|
||||||
score: 100
|
|
||||||
- task: lrucache
|
|
||||||
score: 100
|
|
||||||
- task: externalsort
|
|
||||||
score: 100
|
|
||||||
- task: retryupdate
|
|
||||||
score: 100
|
|
||||||
- task: ciletters
|
|
||||||
score: 100
|
|
||||||
|
|
||||||
- group: Basics
|
|
||||||
start: 18-02-2023 16:00
|
|
||||||
deadline: 28-02-2023 23:59
|
|
||||||
tasks:
|
|
||||||
- task: hotelbusiness
|
|
||||||
score: 100
|
|
||||||
- task: hogwarts
|
|
||||||
score: 100
|
|
||||||
- task: utf8
|
|
||||||
score: 100
|
|
||||||
- task: varfmt
|
|
||||||
score: 100
|
|
||||||
- task: speller
|
|
||||||
score: 100
|
|
||||||
- task: forth
|
|
||||||
score: 100
|
|
||||||
|
|
||||||
- group: Hello World
|
|
||||||
start: 11-02-2023 18:00
|
|
||||||
deadline: 21-02-2023 23:59
|
|
||||||
tasks:
|
|
||||||
- task: sum
|
|
||||||
score: 100
|
|
||||||
- task: tour0
|
|
||||||
score: 100
|
|
||||||
- task: wordcount
|
|
||||||
score: 100
|
|
||||||
- task: urlfetch
|
|
||||||
score: 100
|
|
||||||
- task: fetchall
|
|
||||||
score: 100
|
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -3,3 +3,7 @@
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
/example/
|
/example/
|
||||||
|
|
||||||
|
# Go profiling files
|
||||||
|
*.out
|
||||||
|
*.test
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
grade:
|
grade:
|
||||||
image: cr.yandex/crp9onavos88ug32d5r2/grader/go
|
tags:
|
||||||
variables:
|
- experimental
|
||||||
DOCKER_HOST: tcp://docker:2375/
|
image: gitlab.manytask.org:5050/go/public-2024-spring
|
||||||
DOCKER_TLS_CERTDIR: ""
|
|
||||||
APP_HOST: docker
|
|
||||||
# services:
|
|
||||||
#- docker:dind
|
|
||||||
script:
|
script:
|
||||||
- testtool grade
|
- testtool grade
|
||||||
timeout: 10 minutes
|
timeout: 10 minutes
|
||||||
|
|
263
.manytask.yml
Normal file
263
.manytask.yml
Normal file
|
@ -0,0 +1,263 @@
|
||||||
|
version: 1
|
||||||
|
|
||||||
|
|
||||||
|
settings: # required
|
||||||
|
course_name: go
|
||||||
|
|
||||||
|
gitlab_base_url: https://gitlab.manytask.org
|
||||||
|
public_repo: go/public-2024-spring
|
||||||
|
students_group: go/students-2024-spring
|
||||||
|
|
||||||
|
|
||||||
|
ui:
|
||||||
|
task_url_template: https://github.com/slon/shad-go/tree/main/$TASK_NAME
|
||||||
|
|
||||||
|
# optional, any number of links
|
||||||
|
links:
|
||||||
|
"TG Channel": https://t.me/+eb5z6ZS-sI8xZDNi
|
||||||
|
"TG Chat": https://t.me/+Tk8VTMAk5Tlp7Txm
|
||||||
|
"LMS": https://lk.yandexdataschool.ru/
|
||||||
|
"Contribute Manytask": https://github.com/manytask
|
||||||
|
|
||||||
|
|
||||||
|
deadlines:
|
||||||
|
timezone: Europe/Moscow
|
||||||
|
|
||||||
|
deadlines: hard # hard/interpolate
|
||||||
|
# max_submissions: 10 # optional
|
||||||
|
# submission_penalty: 0.1 # optional
|
||||||
|
|
||||||
|
schedule:
|
||||||
|
- group: Hello World
|
||||||
|
start: 2024-01-01 18:00
|
||||||
|
steps:
|
||||||
|
0.3: 2024-02-27 23:59
|
||||||
|
end: 2024-07-10 23:59
|
||||||
|
tasks:
|
||||||
|
- task: sum
|
||||||
|
score: 100
|
||||||
|
- task: tour0
|
||||||
|
score: 100
|
||||||
|
- task: wordcount
|
||||||
|
score: 100
|
||||||
|
- task: urlfetch
|
||||||
|
score: 100
|
||||||
|
- task: fetchall
|
||||||
|
score: 100
|
||||||
|
|
||||||
|
- group: Basics
|
||||||
|
start: 2024-02-24 13:00
|
||||||
|
steps:
|
||||||
|
0.3: 2024-03-06 06:00
|
||||||
|
end: 2024-07-10 23:59
|
||||||
|
tasks:
|
||||||
|
- task: hotelbusiness
|
||||||
|
score: 100
|
||||||
|
- task: hogwarts
|
||||||
|
score: 100
|
||||||
|
- task: utf8
|
||||||
|
score: 100
|
||||||
|
- task: varfmt
|
||||||
|
score: 100
|
||||||
|
- task: speller
|
||||||
|
score: 100
|
||||||
|
- task: forth
|
||||||
|
score: 100
|
||||||
|
|
||||||
|
- group: Interfaces
|
||||||
|
start: 2024-03-02 13:00
|
||||||
|
steps:
|
||||||
|
0.3: 2024-03-12 23:59
|
||||||
|
end: 2024-07-10 23:59
|
||||||
|
tasks:
|
||||||
|
- task: otp
|
||||||
|
score: 100
|
||||||
|
- task: retryupdate
|
||||||
|
score: 100
|
||||||
|
- task: lrucache
|
||||||
|
score: 100
|
||||||
|
- task: externalsort
|
||||||
|
score: 100
|
||||||
|
- task: ciletters
|
||||||
|
score: 100
|
||||||
|
|
||||||
|
- group: Goroutines
|
||||||
|
start: 2024-03-03 13:00
|
||||||
|
steps:
|
||||||
|
0.3: 2024-03-19 23:59
|
||||||
|
end: 2024-07-10 23:59
|
||||||
|
tasks:
|
||||||
|
- task: tour1
|
||||||
|
score: 100
|
||||||
|
- task: once
|
||||||
|
score: 100
|
||||||
|
- task: rwmutex
|
||||||
|
score: 100
|
||||||
|
- task: waitgroup
|
||||||
|
score: 100
|
||||||
|
- task: cond
|
||||||
|
score: 100
|
||||||
|
- task: ratelimit
|
||||||
|
score: 100
|
||||||
|
|
||||||
|
- group: "[HW] Gitfame"
|
||||||
|
start: 2024-03-09 13:00
|
||||||
|
end: 2024-03-24 23:59
|
||||||
|
tasks:
|
||||||
|
- task: gitfame
|
||||||
|
score: 0
|
||||||
|
|
||||||
|
- group: Testing
|
||||||
|
start: 2024-03-16 13:00
|
||||||
|
steps:
|
||||||
|
0.3: 2024-03-27 23:59
|
||||||
|
end: 2024-07-10 23:59
|
||||||
|
tasks:
|
||||||
|
- task: testequal
|
||||||
|
score: 100
|
||||||
|
- task: fileleak
|
||||||
|
score: 100
|
||||||
|
- task: tabletest
|
||||||
|
score: 100
|
||||||
|
- task: tparallel
|
||||||
|
score: 200
|
||||||
|
- task: iprange
|
||||||
|
score: 100
|
||||||
|
|
||||||
|
- group: Concurrency with shared memory
|
||||||
|
start: 2024-03-30 13:00
|
||||||
|
steps:
|
||||||
|
0.3: 2024-04-10 23:59
|
||||||
|
end: 2024-07-10 23:59
|
||||||
|
tasks:
|
||||||
|
- task: dupcall
|
||||||
|
score: 200
|
||||||
|
- task: keylock
|
||||||
|
score: 200
|
||||||
|
- task: batcher
|
||||||
|
score: 200
|
||||||
|
- task: pubsub
|
||||||
|
score: 300
|
||||||
|
|
||||||
|
- group: HTTP
|
||||||
|
start: 2024-04-06 13:00
|
||||||
|
steps:
|
||||||
|
0.3: 2024-04-16 23:59
|
||||||
|
end: 2024-07-10 23:59
|
||||||
|
tasks:
|
||||||
|
- task: urlshortener
|
||||||
|
score: 100
|
||||||
|
- task: digitalclock
|
||||||
|
score: 100
|
||||||
|
- task: middleware
|
||||||
|
score: 200
|
||||||
|
- task: firewall
|
||||||
|
score: 200
|
||||||
|
- task: olympics
|
||||||
|
score: 200
|
||||||
|
|
||||||
|
- group: SQL
|
||||||
|
start: 2024-04-13 13:00
|
||||||
|
steps:
|
||||||
|
0.3: 2024-04-23 23:59
|
||||||
|
end: 2024-07-10 23:59
|
||||||
|
tasks:
|
||||||
|
- task: dao
|
||||||
|
score: 100
|
||||||
|
- task: ledger
|
||||||
|
score: 200
|
||||||
|
- task: shopfront
|
||||||
|
score: 100
|
||||||
|
- task: wscat
|
||||||
|
score: 200
|
||||||
|
|
||||||
|
- group: "[HW] Dist Build"
|
||||||
|
start: 2024-04-13 13:00
|
||||||
|
end: 2024-05-13 23:59
|
||||||
|
tasks:
|
||||||
|
- task: distbuild
|
||||||
|
score: 1
|
||||||
|
|
||||||
|
- group: Generics
|
||||||
|
start: 2024-04-20 13:00
|
||||||
|
steps:
|
||||||
|
0.3: 2024-05-02 23:59
|
||||||
|
end: 2024-07-10 23:59
|
||||||
|
tasks:
|
||||||
|
- task: genericsum
|
||||||
|
score: 100
|
||||||
|
- task: treeiter
|
||||||
|
score: 100
|
||||||
|
- task: coverme
|
||||||
|
score: 300
|
||||||
|
|
||||||
|
- group: Reflect
|
||||||
|
start: 2024-04-27 13:00
|
||||||
|
steps:
|
||||||
|
0.3: 2024-05-07 23:59
|
||||||
|
end: 2024-07-10 23:59
|
||||||
|
tasks:
|
||||||
|
- task: reversemap
|
||||||
|
score: 100
|
||||||
|
- task: jsonlist
|
||||||
|
score: 100
|
||||||
|
- task: jsonrpc
|
||||||
|
score: 100
|
||||||
|
- task: structtags
|
||||||
|
score: 100
|
||||||
|
|
||||||
|
- group: Low level
|
||||||
|
start: 2024-05-04 13:00
|
||||||
|
steps:
|
||||||
|
0.3: 2024-05-14 23:59
|
||||||
|
end: 2024-07-10 23:59
|
||||||
|
tasks:
|
||||||
|
- task: illegal
|
||||||
|
score: 100
|
||||||
|
- task: blowfish
|
||||||
|
score: 100
|
||||||
|
- task: gzep
|
||||||
|
score: 100
|
||||||
|
|
||||||
|
- group: Analysis
|
||||||
|
start: 2024-05-11 13:00
|
||||||
|
steps:
|
||||||
|
0.3: 2024-05-21 23:59
|
||||||
|
end: 2024-07-10 23:59
|
||||||
|
tasks:
|
||||||
|
- task: testifycheck
|
||||||
|
score: 200
|
||||||
|
|
||||||
|
- group: Bonus
|
||||||
|
start: 2024-03-03 13:00
|
||||||
|
end: 2024-07-10 23:59
|
||||||
|
tasks:
|
||||||
|
- task: yamlembed
|
||||||
|
is_bonus: true
|
||||||
|
score: 100
|
||||||
|
- task: consistenthash
|
||||||
|
is_bonus: true
|
||||||
|
score: 200
|
||||||
|
- task: gossip
|
||||||
|
is_bonus: true
|
||||||
|
score: 300
|
||||||
|
- task: smartsched
|
||||||
|
is_bonus: true
|
||||||
|
score: 200
|
||||||
|
watch:
|
||||||
|
- distbuild/pkg/scheduler
|
||||||
|
- task: wasm
|
||||||
|
is_bonus: true
|
||||||
|
score: 300
|
||||||
|
- task: firegod
|
||||||
|
is_bonus: true
|
||||||
|
score: 200
|
||||||
|
- task: excelwriter
|
||||||
|
is_bonus: true
|
||||||
|
score: 200
|
||||||
|
- task: rsem
|
||||||
|
is_bonus: true
|
||||||
|
score: 200
|
||||||
|
- task: psycher
|
||||||
|
is_bonus: true
|
||||||
|
score: 200
|
1
.private
1
.private
|
@ -1 +1,2 @@
|
||||||
wasm/flappygopher/main_solution.go
|
wasm/flappygopher/main_solution.go
|
||||||
|
rsem/try_lock.lua
|
||||||
|
|
|
@ -1,11 +1,5 @@
|
||||||
check:
|
check:
|
||||||
image: cr.yandex/crp9onavos88ug32d5r2/grader/go-build
|
image: gitlab.manytask.org:5050/go/public-2024-spring/build
|
||||||
variables:
|
|
||||||
DOCKER_HOST: tcp://docker:2375/
|
|
||||||
DOCKER_TLS_CERTDIR: ""
|
|
||||||
APP_HOST: docker
|
|
||||||
# services:
|
|
||||||
#- docker:dind
|
|
||||||
script:
|
script:
|
||||||
- golangci-lint run --build-tags private,solution ./...
|
- golangci-lint run --build-tags private,solution ./...
|
||||||
#- go test -v -tags private,solution ./...
|
#- go test -v -tags private,solution ./...
|
||||||
|
@ -19,8 +13,8 @@ rebuild-base-image:
|
||||||
- docker
|
- docker
|
||||||
when: manual
|
when: manual
|
||||||
script:
|
script:
|
||||||
- docker build -f build.docker -t cr.yandex/crp9onavos88ug32d5r2/grader/go-build .
|
- docker build -f build.docker -t gitlab.manytask.org:5050/go/public-2024-spring/build .
|
||||||
- docker push cr.yandex/crp9onavos88ug32d5r2/grader/go-build:latest
|
- docker push gitlab.manytask.org:5050/go/public-2024-spring/build:latest
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
only:
|
only:
|
||||||
|
@ -28,9 +22,9 @@ deploy:
|
||||||
tags:
|
tags:
|
||||||
- docker
|
- docker
|
||||||
script:
|
script:
|
||||||
- docker pull cr.yandex/crp9onavos88ug32d5r2/grader/go-build:latest
|
- docker pull gitlab.manytask.org:5050/go/public-2024-spring/build:latest
|
||||||
- docker build -f testenv.docker -t cr.yandex/crp9onavos88ug32d5r2/grader/go .
|
- docker build -f testenv.docker -t gitlab.manytask.org:5050/go/public-2024-spring .
|
||||||
- docker push cr.yandex/crp9onavos88ug32d5r2/grader/go:latest
|
- docker push gitlab.manytask.org:5050/go/public-2024-spring:latest
|
||||||
|
|
||||||
build-slides:
|
build-slides:
|
||||||
only:
|
only:
|
||||||
|
@ -38,28 +32,32 @@ build-slides:
|
||||||
tags:
|
tags:
|
||||||
- docker
|
- docker
|
||||||
script:
|
script:
|
||||||
- docker build lectures -t cr.yandex/crp9onavos88ug32d5r2/go-lectures
|
- docker build lectures -t gitlab.manytask.org:5050/go/public-2024-spring/lectures
|
||||||
- docker push cr.yandex/crp9onavos88ug32d5r2/go-lectures
|
- docker push gitlab.manytask.org:5050/go/public-2024-spring/lectures
|
||||||
|
|
||||||
push-to-public:
|
update-config:
|
||||||
stage: .post
|
|
||||||
image: cr.yandex/crp9onavos88ug32d5r2/grader/go
|
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
script:
|
script:
|
||||||
- git remote rm public || true
|
- >
|
||||||
- git remote add -f public https://svparamoshkin:${CI_PUSH_TOKEN}@gitlab.manytask.org/go/public-itmo-2023-fall
|
curl -v --fail --silent -X POST \
|
||||||
- git config --global user.email 'svparamoshkin@yandex-team.ru'
|
-H "Authorization: Bearer $TESTER_TOKEN" \
|
||||||
- git config --global user.name 'svparamoshkin'
|
-H "Content-type: application/x-yaml" \
|
||||||
- git fetch public
|
--data-binary "@.manytask.yml" \
|
||||||
- git branch -D public || true
|
https://go.manytask.org/api/update_config
|
||||||
- git branch public public/master
|
- >
|
||||||
- testtool export --push --move-to-master=false
|
curl -v --fail --silent -X POST \
|
||||||
- curl -F token=$TESTER_TOKEN http://itmo-go.manytask.org/api/sync_task_columns
|
-H "Authorization: Bearer $TESTER_TOKEN" \
|
||||||
|
https://go.manytask.org/api/update_cache
|
||||||
|
|
||||||
push-to-github:
|
push-to-public:
|
||||||
stage: .post
|
stage: .post
|
||||||
image: cr.yandex/crp9onavos88ug32d5r2/grader/go
|
image: gitlab.manytask.org:5050/go/public-2024-spring
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- REMOTE:
|
||||||
|
- git@github.com:slon/shad-go.git
|
||||||
|
- git@gitlab.manytask.org:go/public-2024-spring.git
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
script:
|
script:
|
||||||
|
@ -69,7 +67,7 @@ push-to-github:
|
||||||
- git branch -D main || true
|
- git branch -D main || true
|
||||||
- git checkout -b main
|
- git checkout -b main
|
||||||
- git remote rm github || true
|
- git remote rm github || true
|
||||||
- env GIT_SSH_COMMAND="ssh -i ${PWD}/private.key -o StrictHostKeyChecking=no" git remote add -f github git@github.com:slon/shad-go.git
|
- env GIT_SSH_COMMAND="ssh -i ${PWD}/private.key -o StrictHostKeyChecking=no" git remote add -f github $REMOTE
|
||||||
- env GIT_SSH_COMMAND="ssh -i ${PWD}/private.key -o StrictHostKeyChecking=no" git push github main
|
- env GIT_SSH_COMMAND="ssh -i ${PWD}/private.key -o StrictHostKeyChecking=no" git push github main
|
||||||
|
|
||||||
deploy-slides:
|
deploy-slides:
|
||||||
|
@ -79,5 +77,5 @@ deploy-slides:
|
||||||
tags:
|
tags:
|
||||||
- web
|
- web
|
||||||
script:
|
script:
|
||||||
- docker pull cr.yandex/crp9onavos88ug32d5r2/go-lectures
|
- docker pull gitlab.manytask.org:5050/go/public-2024-spring/lectures
|
||||||
- cd /srv/manytask/go && docker compose up -d
|
- cd /srv/manytask/go && docker compose up -d
|
||||||
|
|
|
@ -1,26 +1,28 @@
|
||||||
# Как послать патч
|
# Как послать патч
|
||||||
|
|
||||||
Если вы нашли недоработку в тестах или неточность/опечатку в условии, то вы можете послать MR
|
Если вы нашли недоработку в тестах или неточность/опечатку в условии, то вы можете послать PR
|
||||||
с исправлением в репозиторий курса.
|
с исправлением в репозиторий курса.
|
||||||
|
|
||||||
За все исправления начисляются дополнительные баллы в колонке bugs в таблице.
|
За все исправления начисляются дополнительные баллы в колонке bonus в таблице.
|
||||||
Размер дополнительных баллов зависит от серьёзности исправления и определяется преподавателями.
|
Размер дополнительных баллов зависит от серьёзности исправления и определяется преподавателями.
|
||||||
|
|
||||||
## Небольшие исправления
|
## Небольшие исправления
|
||||||
|
|
||||||
Небольшие исправления на <10 строк проще всего послать через веб интерфейс гитлаба.
|
Небольшие исправления на <10 строк проще всего послать через веб интерфейс гитхаба.
|
||||||
|
|
||||||
1. Откройте нужный файл в веб интерфейсе репозитория https://gitlab.com/manytask/itmo-go/private
|
1. Откройте нужный файл в веб интерфейсе репозитория https://github.com/slon/shad-go
|
||||||
2. Нажмите на кнопку "Edit". Во всплывающей подсказке нажмите кнопку "Fork".
|
2. Нажмите на кнопку "Edit in place".
|
||||||
![](docs/edit-and-fork.png)
|
![](docs/edit-in-place.png)
|
||||||
3. Внесите изменения в файл. Нажмите "Commit Changes" внизу страницы.
|
3. На следующем экране нажмите "Fork this repository".
|
||||||
4. Добавьте описание вашего изменения. Нажмите "Submit Merge Request".
|
3. Внесите изменения в файл. Нажмите "Commit Changes" сверху страницы.
|
||||||
|
4. Добавьте описание вашего изменения. Нажмите "Propose changed".
|
||||||
|
5. Нажмите "Create pull request".
|
||||||
|
|
||||||
## Продвинутые исправления
|
## Продвинутые исправления
|
||||||
|
|
||||||
Для многофайловых исправлений можно сначала сделать исправление локально:
|
Для многофайловых исправлений можно сначала сделать исправление локально:
|
||||||
|
|
||||||
1. Создайте форк https://gitlab.com/manytask/itmo-go/private аналогично тому, что выше.
|
1. Создайте форк https://github.com/slon/shad-go аналогично тому, что выше.
|
||||||
|
|
||||||
2. Закоммитьте все локальные изменения, которые вы не хотите добавлять в репозиторий курса.
|
2. Закоммитьте все локальные изменения, которые вы не хотите добавлять в репозиторий курса.
|
||||||
|
|
||||||
|
@ -30,16 +32,13 @@
|
||||||
git checkout origin/master -b newbranchforupdate
|
git checkout origin/master -b newbranchforupdate
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Внесите локальные изменения и запушьте их в свой форк на [gitlab.com](https://gitlab.com/) (не в `student`), например
|
4. Внесите локальные изменения и запушьте их в свой форк на [github.com](https://github.com/) (не в `student`), например
|
||||||
```
|
```
|
||||||
git add .
|
git add .
|
||||||
git commit -m "Update tests"
|
git commit -m "Update tests"
|
||||||
git push https://gitlab.com/%USERNAME%/shad-go/
|
git push https://github.com/%USERNAME%/shad-go/
|
||||||
```
|
```
|
||||||
|
|
||||||
5. В своём форке выберите созданную ветку и создайте Merge Request в репозиторий курса. Обычно GitLab подсказывает недавно запушенную ветку и предлагает создать для неё MR.
|
5. В своём форке выберите созданную ветку и создайте Pull Request в репозиторий курса. Обычно Github подсказывает недавно запушенную ветку и предлагает создать для неё PR.
|
||||||
|
|
||||||
![](docs/create-mr.png)
|
На странице c формой нового Pull Request убедитесь, что ветвь назначения — `slon/shad-go:master`. Нажмите кнопку "Create Pull Request".
|
||||||
|
|
||||||
На странице c формой нового Merge Request убедитесь, что ветвь назначения — `slon/shad-go:master`. Нажмите кнопку "Create Merge Request".
|
|
||||||
![](docs/create-mr-form.png)
|
|
||||||
|
|
|
@ -1,13 +1,5 @@
|
||||||
# Курс по Го в ШАД
|
# Курс по Го в ШАД
|
||||||
|
|
||||||
Для работы с кодом нужен go 1.18 или выше.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git clone https://gitlab.com/manytask/itmo-go/private.git
|
|
||||||
cd shad-go
|
|
||||||
go test ./sum/...
|
|
||||||
```
|
|
||||||
|
|
||||||
Проект можно открыть в любой go IDE с поддержкой модулей.
|
Проект можно открыть в любой go IDE с поддержкой модулей.
|
||||||
|
|
||||||
## Информация
|
## Информация
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
```
|
```
|
||||||
goos: linux
|
goos: linux
|
||||||
goarch: amd64
|
goarch: amd64
|
||||||
pkg: gitlab.com/manytask/itmo-go/private/allocs
|
pkg: gitlab.com/slon/shad-go/allocs
|
||||||
Benchmark/count-4 73200 16294 ns/op 880 B/op 5 allocs/op
|
Benchmark/count-4 73200 16294 ns/op 880 B/op 5 allocs/op
|
||||||
Benchmark/main-4 40485 30113 ns/op 1034 B/op 9 allocs/op
|
Benchmark/main-4 40485 30113 ns/op 1034 B/op 9 allocs/op
|
||||||
```
|
```
|
||||||
|
@ -23,7 +23,7 @@ Benchmark/main-4 40485 30113 ns/op 1034
|
||||||
Значения бенчмарков для авторского решения:
|
Значения бенчмарков для авторского решения:
|
||||||
```goos: linux
|
```goos: linux
|
||||||
goarch: amd64
|
goarch: amd64
|
||||||
pkg: gitlab.com/manytask/itmo-go/private/allocs
|
pkg: gitlab.com/slon/shad-go/allocs
|
||||||
Benchmark/count-4 212850 5471 ns/op 4144 B/op 2 allocs/op
|
Benchmark/count-4 212850 5471 ns/op 4144 B/op 2 allocs/op
|
||||||
Benchmark/main-4 143937 8247 ns/op 4176 B/op 3 allocs/op
|
Benchmark/main-4 143937 8247 ns/op 4176 B/op 3 allocs/op
|
||||||
```
|
```
|
||||||
|
|
|
@ -5,7 +5,6 @@ package allocs
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -24,7 +23,7 @@ func NewBaselineCounter() Counter {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c BaselineCounter) Count(r io.Reader) error {
|
func (c BaselineCounter) Count(r io.Reader) error {
|
||||||
data, err := ioutil.ReadAll(r)
|
data, err := io.ReadAll(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,10 @@
|
||||||
|
|
||||||
package batcher
|
package batcher
|
||||||
|
|
||||||
import "gitlab.com/manytask/itmo-go/private/batcher/slow"
|
import "gitlab.com/slon/shad-go/batcher/slow"
|
||||||
|
|
||||||
type Batcher struct{}
|
type Batcher struct {
|
||||||
|
}
|
||||||
|
|
||||||
func NewBatcher(v *slow.Value) *Batcher {
|
func NewBatcher(v *slow.Value) *Batcher {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.uber.org/goleak"
|
"go.uber.org/goleak"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/batcher/slow"
|
"gitlab.com/slon/shad-go/batcher/slow"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSimple(t *testing.T) {
|
func TestSimple(t *testing.T) {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/blowfish"
|
"gitlab.com/slon/shad-go/blowfish"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ cipher.Block = (*blowfish.Blowfish)(nil)
|
var _ cipher.Block = (*blowfish.Blowfish)(nil)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM golang:1.20
|
FROM golang:1.22
|
||||||
|
|
||||||
# enable backports for git-filter-repo
|
# enable backports for git-filter-repo
|
||||||
RUN echo "deb http://deb.debian.org/debian bullseye-backports main" >> /etc/apt/sources.list.d/backports.list
|
RUN echo "deb http://deb.debian.org/debian bullseye-backports main" >> /etc/apt/sources.list.d/backports.list
|
||||||
|
@ -7,4 +7,4 @@ RUN apt-get update && apt-get install -y \
|
||||||
rsync libssl-dev postgresql sudo redis-server git-filter-repo/bullseye-backports \
|
rsync libssl-dev postgresql sudo redis-server git-filter-repo/bullseye-backports \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
RUN curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.51.1
|
RUN curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.56.2
|
||||||
|
|
|
@ -35,7 +35,7 @@ Your pipeline #194613 has failed! // 194613 -- это ID pipeline'а
|
||||||
// Далее идут последние 10 строк лога gitlab runner'а
|
// Далее идут последние 10 строк лога gitlab runner'а
|
||||||
testtool: copying go.mod, go.sum and .golangci.yml
|
testtool: copying go.mod, go.sum and .golangci.yml
|
||||||
testtool: running tests
|
testtool: running tests
|
||||||
testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/manytask/itmo-go/private/sum
|
testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/slon/shad-go/sum
|
||||||
--- FAIL: TestSum (0.00s)
|
--- FAIL: TestSum (0.00s)
|
||||||
sum_test.go:19: 2 + 2 == 0 != 4
|
sum_test.go:19: 2 + 2 == 0 != 4
|
||||||
sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808
|
sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/tools/testtool"
|
"gitlab.com/slon/shad-go/tools/testtool"
|
||||||
)
|
)
|
||||||
|
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
|
@ -93,7 +93,7 @@ testtool: copying !change files
|
||||||
testtool: copying testdata directory
|
testtool: copying testdata directory
|
||||||
testtool: copying go.mod, go.sum and .golangci.yml
|
testtool: copying go.mod, go.sum and .golangci.yml
|
||||||
testtool: running tests
|
testtool: running tests
|
||||||
testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/manytask/itmo-go/private/sum
|
testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/slon/shad-go/sum
|
||||||
--- FAIL: TestSum (0.00s)
|
--- FAIL: TestSum (0.00s)
|
||||||
sum_test.go:19: 2 + 2 == 0 != 4
|
sum_test.go:19: 2 + 2 == 0 != 4
|
||||||
sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808
|
sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808
|
||||||
|
@ -113,7 +113,7 @@ ERROR: Job failed: exit code 1`,
|
||||||
Stage: test, Job grade
|
Stage: test, Job grade
|
||||||
testtool: copying go.mod, go.sum and .golangci.yml
|
testtool: copying go.mod, go.sum and .golangci.yml
|
||||||
testtool: running tests
|
testtool: running tests
|
||||||
testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/manytask/itmo-go/private/sum
|
testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/slon/shad-go/sum
|
||||||
--- FAIL: TestSum (0.00s)
|
--- FAIL: TestSum (0.00s)
|
||||||
sum_test.go:19: 2 + 2 == 0 != 4
|
sum_test.go:19: 2 + 2 == 0 != 4
|
||||||
sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808
|
sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808
|
||||||
|
@ -156,7 +156,7 @@ testtool: copying !change files
|
||||||
testtool: copying testdata directory
|
testtool: copying testdata directory
|
||||||
testtool: copying go.mod, go.sum and .golangci.yml
|
testtool: copying go.mod, go.sum and .golangci.yml
|
||||||
testtool: running tests
|
testtool: running tests
|
||||||
testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/manytask/itmo-go/private/sum
|
testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/slon/shad-go/sum
|
||||||
--- FAIL: TestSum (0.00s)
|
--- FAIL: TestSum (0.00s)
|
||||||
sum_test.go:19: 2 + 2 == 0 != 4
|
sum_test.go:19: 2 + 2 == 0 != 4
|
||||||
sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808
|
sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808
|
||||||
|
@ -188,7 +188,7 @@ ERROR: Job failed: exit code 1`,
|
||||||
Stage: %v, Job %v
|
Stage: %v, Job %v
|
||||||
testtool: copying go.mod, go.sum and .golangci.yml
|
testtool: copying go.mod, go.sum and .golangci.yml
|
||||||
testtool: running tests
|
testtool: running tests
|
||||||
testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/manytask/itmo-go/private/sum
|
testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/slon/shad-go/sum
|
||||||
--- FAIL: TestSum (0.00s)
|
--- FAIL: TestSum (0.00s)
|
||||||
sum_test.go:19: 2 + 2 == 0 != 4
|
sum_test.go:19: 2 + 2 == 0 != 4
|
||||||
sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808
|
sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package cond
|
package cond
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"gitlab.com/slon/shad-go/tools/testtool"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -44,6 +45,38 @@ func TestCondSignal(t *testing.T) {
|
||||||
c.Signal()
|
c.Signal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCondSignalOveruse(t *testing.T) {
|
||||||
|
var m sync.Mutex
|
||||||
|
c := New(&m)
|
||||||
|
running := make(chan bool, 1)
|
||||||
|
awake := make(chan bool, 1)
|
||||||
|
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
c.Signal() // Checks if empty signals are not deadlocking
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
m.Lock()
|
||||||
|
running <- true
|
||||||
|
c.Wait() // Checks if it will wait after empty signals
|
||||||
|
awake <- true
|
||||||
|
m.Unlock()
|
||||||
|
|
||||||
|
}()
|
||||||
|
|
||||||
|
<-running
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-awake:
|
||||||
|
t.Fatal("goroutine not asleep")
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
m.Lock()
|
||||||
|
c.Signal()
|
||||||
|
m.Unlock()
|
||||||
|
<-awake // Will deadlock if no goroutine wakes up
|
||||||
|
}
|
||||||
|
|
||||||
func TestCondSignalGenerations(t *testing.T) {
|
func TestCondSignalGenerations(t *testing.T) {
|
||||||
var m sync.Mutex
|
var m sync.Mutex
|
||||||
c := New(&m)
|
c := New(&m)
|
||||||
|
@ -182,3 +215,7 @@ func TestCondSignalStealing(t *testing.T) {
|
||||||
cond.Broadcast()
|
cond.Broadcast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNoSyncPackageImported(t *testing.T) {
|
||||||
|
testtool.CheckForbiddenImport(t, "sync")
|
||||||
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ func TestHash_EvenDistribution(t *testing.T) {
|
||||||
h.AddNode(&n)
|
h.AddNode(&n)
|
||||||
}
|
}
|
||||||
|
|
||||||
counts := map[*node]int{}
|
counts := map[*node]float64{}
|
||||||
const N = 1 << 16
|
const N = 1 << 16
|
||||||
for i := 0; i < N; i++ {
|
for i := 0; i < N; i++ {
|
||||||
counts[h.GetNode(fmt.Sprintf("key%d", i))] += 1
|
counts[h.GetNode(fmt.Sprintf("key%d", i))] += 1
|
||||||
|
@ -65,14 +65,23 @@ func TestHash_EvenDistribution(t *testing.T) {
|
||||||
|
|
||||||
const P = 1 / float64(K)
|
const P = 1 / float64(K)
|
||||||
const variance = N * (P) * (1 - P)
|
const variance = N * (P) * (1 - P)
|
||||||
stddev := math.Sqrt(variance)
|
idealStddev := math.Sqrt(variance)
|
||||||
t.Logf("P = %v, var = %v, stddev = %v", P, variance, stddev)
|
|
||||||
|
t.Logf("P = %v, var = %v, stddev = %v", P, variance, idealStddev)
|
||||||
t.Logf("counts = %v", maps.Values(counts))
|
t.Logf("counts = %v", maps.Values(counts))
|
||||||
|
|
||||||
|
total := float64(N)
|
||||||
|
mean := total / K
|
||||||
|
|
||||||
|
var dispersion float64
|
||||||
for _, count := range counts {
|
for _, count := range counts {
|
||||||
require.Greater(t, count, int(N/K-stddev*10))
|
dispersion += (count - mean) * (count - mean)
|
||||||
require.Less(t, count, int(N/K+stddev*10))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
realStddev := math.Sqrt(dispersion / K)
|
||||||
|
t.Logf("read stddev = %v", realStddev)
|
||||||
|
|
||||||
|
require.Less(t, math.Abs(realStddev-idealStddev)/idealStddev, float64(4))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHash_ConsistentDistribution(t *testing.T) {
|
func TestHash_ConsistentDistribution(t *testing.T) {
|
||||||
|
|
|
@ -12,8 +12,8 @@ import (
|
||||||
"github.com/gorilla/handlers"
|
"github.com/gorilla/handlers"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/coverme/models"
|
"gitlab.com/slon/shad-go/coverme/models"
|
||||||
"gitlab.com/manytask/itmo-go/private/coverme/utils"
|
"gitlab.com/slon/shad-go/coverme/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
type App struct {
|
type App struct {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/coverme/models"
|
"gitlab.com/slon/shad-go/coverme/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
|
|
|
@ -5,8 +5,8 @@ package main
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/coverme/app"
|
"gitlab.com/slon/shad-go/coverme/app"
|
||||||
"gitlab.com/manytask/itmo-go/private/coverme/models"
|
"gitlab.com/slon/shad-go/coverme/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
|
@ -31,18 +31,14 @@ sudo apt install postgresql
|
||||||
Альтернативный способ — запустить бд в докере.
|
Альтернативный способ — запустить бд в докере.
|
||||||
|
|
||||||
Для этого нужно установить docker и docker-compose по инструкции из [dockertest](../dockertest/README.md).
|
Для этого нужно установить docker и docker-compose по инструкции из [dockertest](../dockertest/README.md).
|
||||||
Добиться успешного запуска
|
|
||||||
```
|
|
||||||
go test -v ./dockertest/...
|
|
||||||
```
|
|
||||||
|
|
||||||
Запускать тесты можно будет так:
|
Запускать тесты можно будет так:
|
||||||
```
|
```
|
||||||
(cd dao && docker-compose up -d && sleep 1 && env PGCONN="host=127.0.0.1 port=5432 database=shad-go user=gopher password=pass" go test -v ./... -count=1 || true && docker-compose down)
|
(cd dao && docker compose up -d --wait && env PGCONN="host=127.0.0.1 port=5432 database=shad-go user=gopher password=pass" go test -v ./... -count=1 || true && docker compose down)
|
||||||
```
|
```
|
||||||
Эта команда стартует docker с postgresql, запускает тесты, передав им DSN через переменную окружения, удаляет контейнеры в конце.
|
Эта команда стартует docker с postgresql, запускает тесты, передав им DSN через переменную окружения, удаляет контейнеры в конце.
|
||||||
|
|
||||||
Как подчистить контейнеры, если что-то пошло не так:
|
Как подчистить контейнеры, если что-то пошло не так:
|
||||||
```
|
```
|
||||||
(cd dao && docker-compose down)
|
(cd dao && docker compose down)
|
||||||
```
|
```
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.uber.org/goleak"
|
"go.uber.org/goleak"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/pgfixture"
|
"gitlab.com/slon/shad-go/pgfixture"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDao(t *testing.T) {
|
func TestDao(t *testing.T) {
|
||||||
|
@ -36,7 +36,7 @@ func TestDao(t *testing.T) {
|
||||||
|
|
||||||
alice, err := dao.Lookup(ctx, aliceID)
|
alice, err := dao.Lookup(ctx, aliceID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, alice, User{ID: aliceID, Name: "Alice"})
|
require.Equal(t, User{ID: aliceID, Name: "Alice"}, alice)
|
||||||
|
|
||||||
require.NoError(t, dao.Delete(ctx, bobID))
|
require.NoError(t, dao.Delete(ctx, bobID))
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ func TestDao(t *testing.T) {
|
||||||
require.ErrorIs(t, err, sql.ErrNoRows)
|
require.ErrorIs(t, err, sql.ErrNoRows)
|
||||||
|
|
||||||
require.NoError(t, dao.Update(ctx, &User{ID: charlieID, Name: "Chaplin"}))
|
require.NoError(t, dao.Update(ctx, &User{ID: charlieID, Name: "Chaplin"}))
|
||||||
|
require.Error(t, dao.Update(ctx, &User{ID: 999, Name: "FooBar"}))
|
||||||
|
|
||||||
users, err := dao.List(ctx)
|
users, err := dao.List(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
|
@ -8,3 +8,8 @@ services:
|
||||||
POSTGRES_PASSWORD: pass
|
POSTGRES_PASSWORD: pass
|
||||||
ports:
|
ports:
|
||||||
- 5432:5432
|
- 5432:5432
|
||||||
|
healthcheck:
|
||||||
|
test: [ "CMD-SHELL", "pg_isready -U $${POSTGRES_USER}" ]
|
||||||
|
interval: 1s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 5
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"image/png"
|
"image/png"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
@ -18,10 +17,10 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/tools/testtool"
|
"gitlab.com/slon/shad-go/tools/testtool"
|
||||||
)
|
)
|
||||||
|
|
||||||
const importPath = "gitlab.com/manytask/itmo-go/private/digitalclock"
|
const importPath = "gitlab.com/slon/shad-go/digitalclock"
|
||||||
|
|
||||||
var binCache testtool.BinCache
|
var binCache testtool.BinCache
|
||||||
|
|
||||||
|
@ -125,7 +124,7 @@ func TestDigitalClock_valid(t *testing.T) {
|
||||||
port, stop := startServer(t)
|
port, stop := startServer(t)
|
||||||
defer stop()
|
defer stop()
|
||||||
|
|
||||||
files, err := ioutil.ReadDir("./testdata")
|
files, err := os.ReadDir("./testdata")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
c := &http.Client{Timeout: time.Second * 10}
|
c := &http.Client{Timeout: time.Second * 10}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -17,13 +16,13 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.uber.org/goleak"
|
"go.uber.org/goleak"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/api"
|
"gitlab.com/slon/shad-go/distbuild/pkg/api"
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/artifact"
|
"gitlab.com/slon/shad-go/distbuild/pkg/artifact"
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/client"
|
"gitlab.com/slon/shad-go/distbuild/pkg/client"
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/dist"
|
"gitlab.com/slon/shad-go/distbuild/pkg/dist"
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/filecache"
|
"gitlab.com/slon/shad-go/distbuild/pkg/filecache"
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/worker"
|
"gitlab.com/slon/shad-go/distbuild/pkg/worker"
|
||||||
"gitlab.com/manytask/itmo-go/private/tools/testtool"
|
"gitlab.com/slon/shad-go/tools/testtool"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
@ -50,7 +49,11 @@ type Config struct {
|
||||||
WorkerCount int
|
WorkerCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
func newEnv(t *testing.T, config *Config) (e *env, cancel func()) {
|
func newEnv(t *testing.T, config *Config) (e *env) {
|
||||||
|
t.Cleanup(func() {
|
||||||
|
goleak.VerifyNone(t)
|
||||||
|
})
|
||||||
|
|
||||||
cwd, err := os.Getwd()
|
cwd, err := os.Getwd()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -60,9 +63,9 @@ func newEnv(t *testing.T, config *Config) (e *env, cancel func()) {
|
||||||
rootDir := filepath.Join(absCWD, "workdir", t.Name())
|
rootDir := filepath.Join(absCWD, "workdir", t.Name())
|
||||||
require.NoError(t, os.RemoveAll(rootDir))
|
require.NoError(t, os.RemoveAll(rootDir))
|
||||||
|
|
||||||
if err = os.MkdirAll(rootDir, 0o777); err != nil {
|
if err = os.MkdirAll(rootDir, 0777); err != nil {
|
||||||
if errors.Is(err, os.ErrPermission) {
|
if errors.Is(err, os.ErrPermission) {
|
||||||
rootDir, err = ioutil.TempDir("", "")
|
rootDir, err = os.MkdirTemp("", "")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
} else {
|
} else {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -90,6 +93,10 @@ func newEnv(t *testing.T, config *Config) (e *env, cancel func()) {
|
||||||
env.Logger, err = cfg.Build()
|
env.Logger, err = cfg.Build()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
_ = env.Logger.Sync()
|
||||||
|
})
|
||||||
|
|
||||||
t.Helper()
|
t.Helper()
|
||||||
t.Logf("test is running inside %s; see test.log file for more info", filepath.Join("workdir", t.Name()))
|
t.Logf("test is running inside %s; see test.log file for more info", filepath.Join("workdir", t.Name()))
|
||||||
|
|
||||||
|
@ -100,6 +107,7 @@ func newEnv(t *testing.T, config *Config) (e *env, cancel func()) {
|
||||||
|
|
||||||
var cancelRootContext func()
|
var cancelRootContext func()
|
||||||
env.Ctx, cancelRootContext = context.WithCancel(context.Background())
|
env.Ctx, cancelRootContext = context.WithCancel(context.Background())
|
||||||
|
t.Cleanup(cancelRootContext)
|
||||||
|
|
||||||
env.Client = client.NewClient(
|
env.Client = client.NewClient(
|
||||||
env.Logger.Named("client"),
|
env.Logger.Named("client"),
|
||||||
|
@ -113,6 +121,7 @@ func newEnv(t *testing.T, config *Config) (e *env, cancel func()) {
|
||||||
env.Logger.Named("coordinator"),
|
env.Logger.Named("coordinator"),
|
||||||
coordinatorCache,
|
coordinatorCache,
|
||||||
)
|
)
|
||||||
|
t.Cleanup(env.Coordinator.Stop)
|
||||||
|
|
||||||
router := http.NewServeMux()
|
router := http.NewServeMux()
|
||||||
router.Handle("/coordinator/", http.StripPrefix("/coordinator", env.Coordinator))
|
router.Handle("/coordinator/", http.StripPrefix("/coordinator", env.Coordinator))
|
||||||
|
@ -161,6 +170,11 @@ func newEnv(t *testing.T, config *Config) (e *env, cancel func()) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
cancelRootContext()
|
||||||
|
_ = env.HTTP.Shutdown(context.Background())
|
||||||
|
})
|
||||||
|
|
||||||
for _, w := range env.Workers {
|
for _, w := range env.Workers {
|
||||||
go func(w *worker.Worker) {
|
go func(w *worker.Worker) {
|
||||||
err := w.Run(env.Ctx)
|
err := w.Run(env.Ctx)
|
||||||
|
@ -181,20 +195,14 @@ func newEnv(t *testing.T, config *Config) (e *env, cancel func()) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return env, func() {
|
return env
|
||||||
cancelRootContext()
|
|
||||||
_ = env.HTTP.Shutdown(context.Background())
|
|
||||||
_ = env.Logger.Sync()
|
|
||||||
|
|
||||||
goleak.VerifyNone(t)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newWinFileSink(u *url.URL) (zap.Sink, error) {
|
func newWinFileSink(u *url.URL) (zap.Sink, error) {
|
||||||
if len(u.Opaque) > 0 {
|
if len(u.Opaque) > 0 {
|
||||||
// Remove leading slash left by url.Parse()
|
// Remove leading slash left by url.Parse()
|
||||||
return os.OpenFile(u.Opaque[1:], os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0o644)
|
return os.OpenFile(u.Opaque[1:], os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
|
||||||
}
|
}
|
||||||
// if url.URL is empty, don't panic slice index error
|
// if url.URL is empty, don't panic slice index error
|
||||||
return os.OpenFile(u.Opaque, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0o644)
|
return os.OpenFile(u.Opaque, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package disttest
|
package disttest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
type JobResult struct {
|
type JobResult struct {
|
||||||
|
|
|
@ -2,13 +2,14 @@ package disttest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
var singleWorkerConfig = &Config{WorkerCount: 1}
|
var singleWorkerConfig = &Config{WorkerCount: 1}
|
||||||
|
@ -26,8 +27,7 @@ var echoGraph = build.Graph{
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSingleCommand(t *testing.T) {
|
func TestSingleCommand(t *testing.T) {
|
||||||
env, cancel := newEnv(t, singleWorkerConfig)
|
env := newEnv(t, singleWorkerConfig)
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
recorder := NewRecorder()
|
recorder := NewRecorder()
|
||||||
require.NoError(t, env.Client.Build(env.Ctx, echoGraph, recorder))
|
require.NoError(t, env.Client.Build(env.Ctx, echoGraph, recorder))
|
||||||
|
@ -37,10 +37,9 @@ func TestSingleCommand(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestJobCaching(t *testing.T) {
|
func TestJobCaching(t *testing.T) {
|
||||||
env, cancel := newEnv(t, singleWorkerConfig)
|
env := newEnv(t, singleWorkerConfig)
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
tmpFile, err := ioutil.TempFile("", "")
|
tmpFile, err := os.CreateTemp("", "")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
graph := build.Graph{
|
graph := build.Graph{
|
||||||
|
@ -62,12 +61,12 @@ func TestJobCaching(t *testing.T) {
|
||||||
assert.Len(t, recorder.Jobs, 1)
|
assert.Len(t, recorder.Jobs, 1)
|
||||||
assert.Equal(t, &JobResult{Stdout: "OK\n", Code: new(int)}, recorder.Jobs[build.ID{'a'}])
|
assert.Equal(t, &JobResult{Stdout: "OK\n", Code: new(int)}, recorder.Jobs[build.ID{'a'}])
|
||||||
|
|
||||||
require.NoError(t, ioutil.WriteFile(tmpFile.Name(), []byte("NOTOK\n"), 0o666))
|
require.NoError(t, os.WriteFile(tmpFile.Name(), []byte("NOTOK\n"), 0666))
|
||||||
|
|
||||||
// Second build must get results from cache.
|
// Second build must get results from cache.
|
||||||
require.NoError(t, env.Client.Build(env.Ctx, graph, NewRecorder()))
|
require.NoError(t, env.Client.Build(env.Ctx, graph, NewRecorder()))
|
||||||
|
|
||||||
output, err := ioutil.ReadAll(tmpFile)
|
output, err := io.ReadAll(tmpFile)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, []byte("NOTOK\n"), output)
|
require.Equal(t, []byte("NOTOK\n"), output)
|
||||||
}
|
}
|
||||||
|
@ -94,8 +93,7 @@ var sourceFilesGraph = build.Graph{
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSourceFiles(t *testing.T) {
|
func TestSourceFiles(t *testing.T) {
|
||||||
env, cancel := newEnv(t, singleWorkerConfig)
|
env := newEnv(t, singleWorkerConfig)
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
recorder := NewRecorder()
|
recorder := NewRecorder()
|
||||||
require.NoError(t, env.Client.Build(env.Ctx, sourceFilesGraph, recorder))
|
require.NoError(t, env.Client.Build(env.Ctx, sourceFilesGraph, recorder))
|
||||||
|
@ -125,8 +123,7 @@ var artifactTransferGraph = build.Graph{
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestArtifactTransferBetweenJobs(t *testing.T) {
|
func TestArtifactTransferBetweenJobs(t *testing.T) {
|
||||||
env, cancel := newEnv(t, singleWorkerConfig)
|
env := newEnv(t, singleWorkerConfig)
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
recorder := NewRecorder()
|
recorder := NewRecorder()
|
||||||
require.NoError(t, env.Client.Build(env.Ctx, artifactTransferGraph, recorder))
|
require.NoError(t, env.Client.Build(env.Ctx, artifactTransferGraph, recorder))
|
||||||
|
|
|
@ -9,14 +9,13 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
var threeWorkerConfig = &Config{WorkerCount: 3}
|
var threeWorkerConfig = &Config{WorkerCount: 3}
|
||||||
|
|
||||||
func TestArtifactTransferBetweenWorkers(t *testing.T) {
|
func TestArtifactTransferBetweenWorkers(t *testing.T) {
|
||||||
env, cancel := newEnv(t, threeWorkerConfig)
|
env := newEnv(t, threeWorkerConfig)
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
baseJob := build.Job{
|
baseJob := build.Job{
|
||||||
ID: build.ID{'a'},
|
ID: build.ID{'a'},
|
||||||
|
|
|
@ -3,7 +3,7 @@ package api
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BuildRequest struct {
|
type BuildRequest struct {
|
||||||
|
@ -25,7 +25,8 @@ type BuildFailed struct {
|
||||||
Error string
|
Error string
|
||||||
}
|
}
|
||||||
|
|
||||||
type BuildFinished struct{}
|
type BuildFinished struct {
|
||||||
|
}
|
||||||
|
|
||||||
type UploadDone struct{}
|
type UploadDone struct{}
|
||||||
|
|
||||||
|
@ -33,7 +34,8 @@ type SignalRequest struct {
|
||||||
UploadDone *UploadDone
|
UploadDone *UploadDone
|
||||||
}
|
}
|
||||||
|
|
||||||
type SignalResponse struct{}
|
type SignalResponse struct {
|
||||||
|
}
|
||||||
|
|
||||||
type StatusWriter interface {
|
type StatusWriter interface {
|
||||||
Started(rsp *BuildStarted) error
|
Started(rsp *BuildStarted) error
|
||||||
|
|
|
@ -7,10 +7,11 @@ import (
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BuildClient struct{}
|
type BuildClient struct {
|
||||||
|
}
|
||||||
|
|
||||||
func NewBuildClient(l *zap.Logger, endpoint string) *BuildClient {
|
func NewBuildClient(l *zap.Logger, endpoint string) *BuildClient {
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
|
|
|
@ -12,9 +12,9 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.uber.org/zap/zaptest"
|
"go.uber.org/zap/zaptest"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/api"
|
"gitlab.com/slon/shad-go/distbuild/pkg/api"
|
||||||
mock "gitlab.com/manytask/itmo-go/private/distbuild/pkg/api/mock"
|
mock "gitlab.com/slon/shad-go/distbuild/pkg/api/mock"
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate mockgen -package mock -destination mock/mock.go . Service
|
//go:generate mockgen -package mock -destination mock/mock.go . Service
|
||||||
|
@ -28,7 +28,6 @@ type env struct {
|
||||||
|
|
||||||
func (e *env) stop() {
|
func (e *env) stop() {
|
||||||
e.server.Close()
|
e.server.Close()
|
||||||
e.ctrl.Finish()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newEnv(t *testing.T) (*env, func()) {
|
func newEnv(t *testing.T) (*env, func()) {
|
||||||
|
@ -56,8 +55,8 @@ func TestBuildSignal(t *testing.T) {
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
buildIDa := build.ID{0o1}
|
buildIDa := build.ID{01}
|
||||||
buildIDb := build.ID{0o2}
|
buildIDb := build.ID{02}
|
||||||
req := &api.SignalRequest{}
|
req := &api.SignalRequest{}
|
||||||
rsp := &api.SignalResponse{}
|
rsp := &api.SignalResponse{}
|
||||||
|
|
||||||
|
@ -91,10 +90,10 @@ func TestBuildRunning(t *testing.T) {
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
buildID := build.ID{0o2}
|
buildID := build.ID{02}
|
||||||
|
|
||||||
req := &api.BuildRequest{
|
req := &api.BuildRequest{
|
||||||
Graph: build.Graph{SourceFiles: map[build.ID]string{{0o1}: "a.txt"}},
|
Graph: build.Graph{SourceFiles: map[build.ID]string{{01}: "a.txt"}},
|
||||||
}
|
}
|
||||||
|
|
||||||
started := &api.BuildStarted{ID: buildID}
|
started := &api.BuildStarted{ID: buildID}
|
||||||
|
@ -141,7 +140,7 @@ func TestBuildResultsStreaming(t *testing.T) {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
buildID := build.ID{0o2}
|
buildID := build.ID{02}
|
||||||
req := &api.BuildRequest{}
|
req := &api.BuildRequest{}
|
||||||
started := &api.BuildStarted{ID: buildID}
|
started := &api.BuildStarted{ID: buildID}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ package api
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
// JobResult описывает результат работы джоба.
|
// JobResult описывает результат работы джоба.
|
||||||
|
|
|
@ -11,16 +11,15 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.uber.org/zap/zaptest"
|
"go.uber.org/zap/zaptest"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/api"
|
"gitlab.com/slon/shad-go/distbuild/pkg/api"
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/api/mock"
|
"gitlab.com/slon/shad-go/distbuild/pkg/api/mock"
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate mockgen -package mock -destination mock/heartbeat.go . HeartbeatService
|
//go:generate mockgen -package mock -destination mock/heartbeat.go . HeartbeatService
|
||||||
|
|
||||||
func TestHeartbeat(t *testing.T) {
|
func TestHeartbeat(t *testing.T) {
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
defer ctrl.Finish()
|
|
||||||
|
|
||||||
l := zaptest.NewLogger(t)
|
l := zaptest.NewLogger(t)
|
||||||
m := mock.NewMockHeartbeatService(ctrl)
|
m := mock.NewMockHeartbeatService(ctrl)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Code generated by MockGen. DO NOT EDIT.
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
// Source: gitlab.com/manytask/itmo-go/private/distbuild/pkg/api (interfaces: HeartbeatService)
|
// Source: gitlab.com/slon/shad-go/distbuild/pkg/api (interfaces: HeartbeatService)
|
||||||
|
|
||||||
// Package mock is a generated GoMock package.
|
// Package mock is a generated GoMock package.
|
||||||
package mock
|
package mock
|
||||||
|
@ -7,7 +7,7 @@ package mock
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
api "gitlab.com/manytask/itmo-go/private/distbuild/pkg/api"
|
api "gitlab.com/slon/shad-go/distbuild/pkg/api"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Code generated by MockGen. DO NOT EDIT.
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
// Source: gitlab.com/manytask/itmo-go/private/distbuild/pkg/api (interfaces: Service)
|
// Source: gitlab.com/slon/shad-go/distbuild/pkg/api (interfaces: Service)
|
||||||
|
|
||||||
// Package mock is a generated GoMock package.
|
// Package mock is a generated GoMock package.
|
||||||
package mock
|
package mock
|
||||||
|
@ -7,8 +7,8 @@ package mock
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
api "gitlab.com/manytask/itmo-go/private/distbuild/pkg/api"
|
api "gitlab.com/slon/shad-go/distbuild/pkg/api"
|
||||||
build "gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
build "gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,11 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -34,18 +33,18 @@ func NewCache(root string) (*Cache, error) {
|
||||||
if err := os.RemoveAll(tmpDir); err != nil {
|
if err := os.RemoveAll(tmpDir); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := os.MkdirAll(tmpDir, 0o777); err != nil {
|
if err := os.MkdirAll(tmpDir, 0777); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cacheDir := filepath.Join(root, "c")
|
cacheDir := filepath.Join(root, "c")
|
||||||
if err := os.MkdirAll(cacheDir, 0o777); err != nil {
|
if err := os.MkdirAll(cacheDir, 0777); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < 256; i++ {
|
for i := 0; i < 256; i++ {
|
||||||
d := hex.EncodeToString([]byte{uint8(i)})
|
d := hex.EncodeToString([]byte{uint8(i)})
|
||||||
if err := os.MkdirAll(filepath.Join(cacheDir, d), 0o777); err != nil {
|
if err := os.MkdirAll(filepath.Join(cacheDir, d), 0777); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,13 +109,13 @@ func (c *Cache) writeUnlock(id build.ID) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) Range(artifactFn func(artifact build.ID) error) error {
|
func (c *Cache) Range(artifactFn func(artifact build.ID) error) error {
|
||||||
shards, err := ioutil.ReadDir(c.cacheDir)
|
shards, err := os.ReadDir(c.cacheDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, shard := range shards {
|
for _, shard := range shards {
|
||||||
dirs, err := ioutil.ReadDir(filepath.Join(c.cacheDir, shard.Name()))
|
dirs, err := os.ReadDir(filepath.Join(c.cacheDir, shard.Name()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -151,7 +150,7 @@ func (c *Cache) Create(artifact build.ID) (path string, commit, abort func() err
|
||||||
}
|
}
|
||||||
|
|
||||||
path = filepath.Join(c.tmpDir, artifact.String())
|
path = filepath.Join(c.tmpDir, artifact.String())
|
||||||
if err = os.MkdirAll(path, 0o777); err != nil {
|
if err = os.MkdirAll(path, 0777); err != nil {
|
||||||
c.writeUnlock(artifact)
|
c.writeUnlock(artifact)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,14 @@ package artifact_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/artifact"
|
"gitlab.com/slon/shad-go/distbuild/pkg/artifact"
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
type testCache struct {
|
type testCache struct {
|
||||||
|
@ -23,7 +22,7 @@ func (c *testCache) cleanup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestCache(t *testing.T) *testCache {
|
func newTestCache(t *testing.T) *testCache {
|
||||||
tmpDir, err := ioutil.TempDir("", "")
|
tmpDir, err := os.MkdirTemp("", "")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
cache, err := artifact.NewCache(tmpDir)
|
cache, err := artifact.NewCache(tmpDir)
|
||||||
|
|
|
@ -5,7 +5,7 @@ package artifact
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Download artifact from remote cache into local cache.
|
// Download artifact from remote cache into local cache.
|
||||||
|
|
|
@ -2,17 +2,17 @@ package artifact_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.uber.org/zap/zaptest"
|
"go.uber.org/zap/zaptest"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/artifact"
|
"gitlab.com/slon/shad-go/distbuild/pkg/artifact"
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestArtifactTransfer(t *testing.T) {
|
func TestArtifactTransfer(t *testing.T) {
|
||||||
|
@ -23,7 +23,7 @@ func TestArtifactTransfer(t *testing.T) {
|
||||||
|
|
||||||
dir, commit, _, err := remoteCache.Create(id)
|
dir, commit, _, err := remoteCache.Create(id)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, ioutil.WriteFile(filepath.Join(dir, "a.txt"), []byte("foobar"), 0o777))
|
require.NoError(t, os.WriteFile(filepath.Join(dir, "a.txt"), []byte("foobar"), 0777))
|
||||||
require.NoError(t, commit())
|
require.NoError(t, commit())
|
||||||
|
|
||||||
l := zaptest.NewLogger(t)
|
l := zaptest.NewLogger(t)
|
||||||
|
@ -42,7 +42,7 @@ func TestArtifactTransfer(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer unlock()
|
defer unlock()
|
||||||
|
|
||||||
content, err := ioutil.ReadFile(filepath.Join(dir, "a.txt"))
|
content, err := os.ReadFile(filepath.Join(dir, "a.txt"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, []byte("foobar"), content)
|
require.Equal(t, []byte("foobar"), content)
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ type Job struct {
|
||||||
// exec - выполняет произвольную команду
|
// exec - выполняет произвольную команду
|
||||||
// cat - записывает строку в файл
|
// cat - записывает строку в файл
|
||||||
//
|
//
|
||||||
// Все строки в описании команды могут содержать в себе на переменные. Перед выполнением
|
// Все строки в описании команды могут содержать в себе ссылки на контекстные переменные. Перед выполнением
|
||||||
// реальной команды, переменные заменяются на их реальные значения.
|
// реальной команды, переменные заменяются на их реальные значения.
|
||||||
//
|
//
|
||||||
// {{.OutputDir}} - абсолютный путь до выходной директории джоба.
|
// {{.OutputDir}} - абсолютный путь до выходной директории джоба.
|
||||||
|
|
|
@ -7,10 +7,11 @@ import (
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct{}
|
type Client struct {
|
||||||
|
}
|
||||||
|
|
||||||
func NewClient(
|
func NewClient(
|
||||||
l *zap.Logger,
|
l *zap.Logger,
|
||||||
|
|
9
distbuild/pkg/dist/coordinator.go
vendored
9
distbuild/pkg/dist/coordinator.go
vendored
|
@ -8,11 +8,12 @@ import (
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/filecache"
|
"gitlab.com/slon/shad-go/distbuild/pkg/filecache"
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/scheduler"
|
"gitlab.com/slon/shad-go/distbuild/pkg/scheduler"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Coordinator struct{}
|
type Coordinator struct {
|
||||||
|
}
|
||||||
|
|
||||||
var defaultConfig = scheduler.Config{
|
var defaultConfig = scheduler.Config{
|
||||||
CacheTimeout: time.Millisecond * 10,
|
CacheTimeout: time.Millisecond * 10,
|
||||||
|
@ -26,6 +27,8 @@ func NewCoordinator(
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Coordinator) Stop() {}
|
||||||
|
|
||||||
func (c *Coordinator) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (c *Coordinator) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,11 @@ import (
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct{}
|
type Client struct {
|
||||||
|
}
|
||||||
|
|
||||||
func NewClient(l *zap.Logger, endpoint string) *Client {
|
func NewClient(l *zap.Logger, endpoint string) *Client {
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
|
|
|
@ -3,9 +3,9 @@ package filecache_test
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -14,8 +14,8 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.uber.org/zap/zaptest"
|
"go.uber.org/zap/zaptest"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/filecache"
|
"gitlab.com/slon/shad-go/distbuild/pkg/filecache"
|
||||||
)
|
)
|
||||||
|
|
||||||
type env struct {
|
type env struct {
|
||||||
|
@ -52,7 +52,7 @@ func TestFileUpload(t *testing.T) {
|
||||||
content := bytes.Repeat([]byte("foobar"), 1024*1024)
|
content := bytes.Repeat([]byte("foobar"), 1024*1024)
|
||||||
|
|
||||||
tmpFilePath := filepath.Join(env.cache.tmpDir, "foo.txt")
|
tmpFilePath := filepath.Join(env.cache.tmpDir, "foo.txt")
|
||||||
require.NoError(t, ioutil.WriteFile(tmpFilePath, content, 0o666))
|
require.NoError(t, os.WriteFile(tmpFilePath, content, 0666))
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ func TestFileUpload(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer unlock()
|
defer unlock()
|
||||||
|
|
||||||
actualContent, err := ioutil.ReadFile(path)
|
actualContent, err := os.ReadFile(path)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, content, actualContent)
|
require.Equal(t, content, actualContent)
|
||||||
})
|
})
|
||||||
|
@ -123,7 +123,7 @@ func TestFileDownload(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer unlock()
|
defer unlock()
|
||||||
|
|
||||||
content, err := ioutil.ReadFile(path)
|
content, err := os.ReadFile(path)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, []byte("foobar"), content)
|
require.Equal(t, []byte("foobar"), content)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/artifact"
|
"gitlab.com/slon/shad-go/distbuild/pkg/artifact"
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -2,14 +2,13 @@ package filecache_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/filecache"
|
"gitlab.com/slon/shad-go/distbuild/pkg/filecache"
|
||||||
)
|
)
|
||||||
|
|
||||||
type testCache struct {
|
type testCache struct {
|
||||||
|
@ -18,7 +17,7 @@ type testCache struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCache(t *testing.T) *testCache {
|
func newCache(t *testing.T) *testCache {
|
||||||
tmpDir, err := ioutil.TempDir("", "filecache")
|
tmpDir, err := os.MkdirTemp("", "filecache")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
c, err := filecache.New(tmpDir)
|
c, err := filecache.New(tmpDir)
|
||||||
|
@ -36,25 +35,25 @@ func (c *testCache) cleanup() {
|
||||||
func TestFileCache(t *testing.T) {
|
func TestFileCache(t *testing.T) {
|
||||||
cache := newCache(t)
|
cache := newCache(t)
|
||||||
|
|
||||||
_, abort, err := cache.Write(build.ID{0o1})
|
_, abort, err := cache.Write(build.ID{01})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, abort())
|
require.NoError(t, abort())
|
||||||
|
|
||||||
_, _, err = cache.Get(build.ID{0o1})
|
_, _, err = cache.Get(build.ID{01})
|
||||||
require.Truef(t, errors.Is(err, filecache.ErrNotFound), "%v", err)
|
require.Truef(t, errors.Is(err, filecache.ErrNotFound), "%v", err)
|
||||||
|
|
||||||
f, _, err := cache.Write(build.ID{0o2})
|
f, _, err := cache.Write(build.ID{02})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = f.Write([]byte("foo bar"))
|
_, err = f.Write([]byte("foo bar"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.Close())
|
require.NoError(t, f.Close())
|
||||||
|
|
||||||
path, unlock, err := cache.Get(build.ID{0o2})
|
path, unlock, err := cache.Get(build.ID{02})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer unlock()
|
defer unlock()
|
||||||
|
|
||||||
content, err := ioutil.ReadFile(path)
|
content, err := os.ReadFile(path)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, []byte("foo bar"), content)
|
require.Equal(t, []byte("foo bar"), content)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ import (
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/api"
|
"gitlab.com/slon/shad-go/distbuild/pkg/api"
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
var TimeAfter = time.After
|
var TimeAfter = time.After
|
||||||
|
@ -25,7 +25,8 @@ type Config struct {
|
||||||
DepsTimeout time.Duration
|
DepsTimeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
type Scheduler struct{}
|
type Scheduler struct {
|
||||||
|
}
|
||||||
|
|
||||||
func NewScheduler(l *zap.Logger, config Config) *Scheduler {
|
func NewScheduler(l *zap.Logger, config Config) *Scheduler {
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
|
@ -46,3 +47,7 @@ func (c *Scheduler) ScheduleJob(job *api.JobSpec) *PendingJob {
|
||||||
func (c *Scheduler) PickJob(ctx context.Context, workerID api.WorkerID) *PendingJob {
|
func (c *Scheduler) PickJob(ctx context.Context, workerID api.WorkerID) *PendingJob {
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Scheduler) Stop() {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package tarstream_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -10,11 +9,11 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/tarstream"
|
"gitlab.com/slon/shad-go/distbuild/pkg/tarstream"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTarStream(t *testing.T) {
|
func TestTarStream(t *testing.T) {
|
||||||
tmpDir, err := ioutil.TempDir("", "tarstream")
|
tmpDir, err := os.MkdirTemp("", "tarstream")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
t.Logf("running inside %s", tmpDir)
|
t.Logf("running inside %s", tmpDir)
|
||||||
|
@ -22,15 +21,15 @@ func TestTarStream(t *testing.T) {
|
||||||
from := filepath.Join(tmpDir, "from")
|
from := filepath.Join(tmpDir, "from")
|
||||||
to := filepath.Join(tmpDir, "to")
|
to := filepath.Join(tmpDir, "to")
|
||||||
|
|
||||||
require.NoError(t, os.Mkdir(from, 0o777))
|
require.NoError(t, os.Mkdir(from, 0777))
|
||||||
require.NoError(t, os.Mkdir(to, 0o777))
|
require.NoError(t, os.Mkdir(to, 0777))
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
require.NoError(t, os.Mkdir(filepath.Join(from, "a"), 0o777))
|
require.NoError(t, os.Mkdir(filepath.Join(from, "a"), 0777))
|
||||||
require.NoError(t, os.MkdirAll(filepath.Join(from, "b", "c", "d"), 0o777))
|
require.NoError(t, os.MkdirAll(filepath.Join(from, "b", "c", "d"), 0777))
|
||||||
require.NoError(t, ioutil.WriteFile(filepath.Join(from, "a", "x.bin"), []byte("xxx"), 0o777))
|
require.NoError(t, os.WriteFile(filepath.Join(from, "a", "x.bin"), []byte("xxx"), 0777))
|
||||||
require.NoError(t, ioutil.WriteFile(filepath.Join(from, "b", "c", "y.txt"), []byte("yyy"), 0o666))
|
require.NoError(t, os.WriteFile(filepath.Join(from, "b", "c", "y.txt"), []byte("yyy"), 0666))
|
||||||
|
|
||||||
require.NoError(t, tarstream.Send(from, &buf))
|
require.NoError(t, tarstream.Send(from, &buf))
|
||||||
|
|
||||||
|
@ -53,15 +52,15 @@ func TestTarStream(t *testing.T) {
|
||||||
|
|
||||||
require.Equal(t, mode.String(), st.Mode().String())
|
require.Equal(t, mode.String(), st.Mode().String())
|
||||||
|
|
||||||
b, err := ioutil.ReadFile(path)
|
b, err := os.ReadFile(path)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, content, b)
|
require.Equal(t, content, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFile(filepath.Join(to, "a", "x.bin"), []byte("xxx"), 0o755)
|
checkFile(filepath.Join(to, "a", "x.bin"), []byte("xxx"), 0755)
|
||||||
checkFile(filepath.Join(to, "b", "c", "y.txt"), []byte("yyy"), 0o644)
|
checkFile(filepath.Join(to, "b", "c", "y.txt"), []byte("yyy"), 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
unix.Umask(0o022)
|
unix.Umask(0022)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,13 @@ import (
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/api"
|
"gitlab.com/slon/shad-go/distbuild/pkg/api"
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/artifact"
|
"gitlab.com/slon/shad-go/distbuild/pkg/artifact"
|
||||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/filecache"
|
"gitlab.com/slon/shad-go/distbuild/pkg/filecache"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Worker struct{}
|
type Worker struct {
|
||||||
|
}
|
||||||
|
|
||||||
func New(
|
func New(
|
||||||
workerID api.WorkerID,
|
workerID api.WorkerID,
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
✗ go test -v -run=^$ -bench=BenchmarkSprintf -memprofile=mem.out ./varfmt/...
|
✗ go test -v -run=^$ -bench=BenchmarkSprintf -memprofile=mem.out ./varfmt/...
|
||||||
goos: linux
|
goos: linux
|
||||||
goarch: amd64
|
goarch: amd64
|
||||||
pkg: gitlab.com/manytask/itmo-go/private/varfmt
|
pkg: gitlab.com/slon/shad-go/varfmt
|
||||||
cpu: Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz
|
cpu: Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz
|
||||||
BenchmarkSprintf
|
BenchmarkSprintf
|
||||||
BenchmarkSprintf/small
|
BenchmarkSprintf/small
|
||||||
|
@ -17,7 +17,7 @@ BenchmarkSprintf/small_string-8 13282659 84.48 ns/op 16 B/op
|
||||||
BenchmarkSprintf/big
|
BenchmarkSprintf/big
|
||||||
BenchmarkSprintf/big-8 20089 62372 ns/op 16388 B/op 1 allocs/op
|
BenchmarkSprintf/big-8 20089 62372 ns/op 16388 B/op 1 allocs/op
|
||||||
PASS
|
PASS
|
||||||
ok gitlab.com/manytask/itmo-go/private/varfmt 4.363s
|
ok gitlab.com/slon/shad-go/varfmt 4.363s
|
||||||
```
|
```
|
||||||
|
|
||||||
Сэмплы профайлера будут записаны в бинарный файл `mem.out`.
|
Сэмплы профайлера будут записаны в бинарный файл `mem.out`.
|
||||||
|
@ -53,7 +53,7 @@ Showing nodes accounting for 715.73MB, 99.37% of 720.23MB total
|
||||||
Dropped 24 nodes (cum <= 3.60MB)
|
Dropped 24 nodes (cum <= 3.60MB)
|
||||||
flat flat% sum% cum cum%
|
flat flat% sum% cum cum%
|
||||||
715.73MB 99.37% 99.37% 716.73MB 99.51% fmt.Sprintf
|
715.73MB 99.37% 99.37% 716.73MB 99.51% fmt.Sprintf
|
||||||
0 0% 99.37% 716.73MB 99.51% gitlab.com/manytask/itmo-go/private/varfmt.BenchmarkSprintf.func1
|
0 0% 99.37% 716.73MB 99.51% gitlab.com/slon/shad-go/varfmt.BenchmarkSprintf.func1
|
||||||
0 0% 99.37% 716.73MB 99.51% testing.(*B).launch
|
0 0% 99.37% 716.73MB 99.51% testing.(*B).launch
|
||||||
0 0% 99.37% 716.73MB 99.51% testing.(*B).runN
|
0 0% 99.37% 716.73MB 99.51% testing.(*B).runN
|
||||||
(pprof)
|
(pprof)
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 67 KiB |
Binary file not shown.
Before Width: | Height: | Size: 27 KiB |
Binary file not shown.
Before Width: | Height: | Size: 128 KiB |
BIN
docs/edit-in-place.png
Normal file
BIN
docs/edit-in-place.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 173 KiB |
|
@ -63,8 +63,8 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/gitfame/configs"
|
"gitlab.com/slon/shad-go/gitfame/configs"
|
||||||
"gitlab.com/manytask/itmo-go/private/gitfame/internal"
|
"gitlab.com/slon/shad-go/gitfame/internal"
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
|
@ -81,8 +81,8 @@ import (
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/gitfame/configs"
|
"gitlab.com/slon/shad-go/gitfame/configs"
|
||||||
"gitlab.com/manytask/itmo-go/private/gitfame/internal"
|
"gitlab.com/slon/shad-go/gitfame/internal"
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
Low-level programming. unsafe. Package binary. bytes.Buffer. cgo, syscall.
|
Low-level programming. unsafe. Package binary. bytes.Buffer. cgo, syscall.
|
||||||
|
|
||||||
11. Архитектура GC. Write barrier. Stack growth. GC pause. GOGC. sync.Pool. Шедулер
|
11. Архитектура GC. Write barrier. Stack growth. GC pause. GOGC. sync.Pool. Шедулер
|
||||||
горутин. GOMACPROCS. Утечка тредов.
|
горутин. GOMAXPROCS. Утечка тредов.
|
||||||
|
|
||||||
12. Go tooling. pprof. CPU and Memory profiling. Кросс-компиляция. GOOS, GOARCH. CGO_ENABLED=0.
|
12. Go tooling. pprof. CPU and Memory profiling. Кросс-компиляция. GOOS, GOARCH. CGO_ENABLED=0.
|
||||||
Build tags. go modules. godoc. Code generation.
|
Build tags. go modules. godoc. Code generation.
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"gitlab.com/slon/shad-go/tools/testtool"
|
||||||
"go.uber.org/goleak"
|
"go.uber.org/goleak"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -38,6 +39,23 @@ func TestCall_Simple(t *testing.T) {
|
||||||
require.Equal(t, 2, called)
|
require.Equal(t, 2, called)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCall_NoBusyWait(t *testing.T) {
|
||||||
|
done := make(chan struct{})
|
||||||
|
defer close(done)
|
||||||
|
|
||||||
|
var call Call
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
go func() {
|
||||||
|
_, _ = call.Do(context.Background(), func(ctx context.Context) (interface{}, error) {
|
||||||
|
<-done
|
||||||
|
return nil, nil
|
||||||
|
})
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
testtool.VerifyNoBusyGoroutines(t)
|
||||||
|
}
|
||||||
|
|
||||||
func TestCall_Dedup(t *testing.T) {
|
func TestCall_Dedup(t *testing.T) {
|
||||||
defer goleak.VerifyNone(t)
|
defer goleak.VerifyNone(t)
|
||||||
|
|
||||||
|
|
67
excelwriter/README.md
Normal file
67
excelwriter/README.md
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
# excelwriter [reflect]
|
||||||
|
|
||||||
|
В этой задаче нужно обернуть библиотеку для работы с exel'ем в reflect, реализовав интерфейс для построчной записи go объектов в excel
|
||||||
|
```go
|
||||||
|
type Writer interface {
|
||||||
|
WriteRow(r any) error
|
||||||
|
}
|
||||||
|
```
|
||||||
|
r — это либо структура, либо map[smth]any, либо указатель на что-то из этого.
|
||||||
|
|
||||||
|
smth — это либо строка, либо тип реализующий [TextMarshaler](https://pkg.go.dev/encoding#TextMarshaler)
|
||||||
|
|
||||||
|
Как должны сериализовываться поля структур подробно написано в интерфейсе.
|
||||||
|
Всё, что не специфицировано в доке и не проверяется тестами можно делать как сочтёте разумным.
|
||||||
|
|
||||||
|
Также нужно реализовать конструктор
|
||||||
|
```go
|
||||||
|
func New(f *excelize.File) Writer {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
принимающий на вход инициализированный excel клиент.
|
||||||
|
Можно считать, что excel файл изначально пустой у которого создана 1 страница. Все записи нужно делать в ней.
|
||||||
|
|
||||||
|
Пример использования
|
||||||
|
```go
|
||||||
|
type Movie struct {
|
||||||
|
Title string
|
||||||
|
Year int `xlsx:"release_year"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func StoreMovies() {
|
||||||
|
f := excelize.NewFile()
|
||||||
|
_, _ = f.NewSheet("Sheet1")
|
||||||
|
|
||||||
|
w := excelwriter.New(f)
|
||||||
|
_ = w.WriteRow(&Movie{Title: "Blade Runner", Year: 1982})
|
||||||
|
_ = w.WriteRow(&Movie{Title: "Blade Runner 2049", Year: 2017})
|
||||||
|
_ = w.WriteRow(map[string]any{"title": "Into the wild", "release_year": 2007})
|
||||||
|
|
||||||
|
out, _ := os.Create("/tmp/movie.xlsx")
|
||||||
|
_, _ = f.WriteTo(out)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
В результате будет создан excel документ со следующим содержимым
|
||||||
|
```
|
||||||
|
title release_year
|
||||||
|
Blade Runner 1982
|
||||||
|
Blade Runner 2049 2017
|
||||||
|
Into the wild 2007
|
||||||
|
```
|
||||||
|
|
||||||
|
В первой строке хранятся имена колонок, которые вычисляются из имён полей, тэгов и ключей map'ов.
|
||||||
|
|
||||||
|
Разные структуры могут превращаться в разные наборы колонок.
|
||||||
|
Для каждого уникального имени должна быть ровно одна колонка, их нужно "создавать" по мере возникновения.
|
||||||
|
|
||||||
|
Новые ключи каждого конкретного мапа добавляются в колонки в отсортированном порядке, чтобы при перезапусках на одних и тех же данных получались одинаковые excel'ки.
|
||||||
|
|
||||||
|
Помимо имён полей в xlsx тэгах для числовых полей нужно поддержать стили форматирования.
|
||||||
|
Например, в excel нет отдельного типа для дат. Дата — это 15-и значный double (excel тип Number) со стилем форматирования `d-mmm-yy`. Библиотека для работы с excel'ем определяет [наборы популярных стилей](https://pkg.go.dev/github.com/xuri/excelize/v2#File.NewStyle) в виде enum'а `15 d-mmm-yy`. Это число 15 и нужно поддержать в тэге `xslx:"date,numfmt:15"`.
|
||||||
|
|
||||||
|
## Вопросы со звёздочкой
|
||||||
|
1. Как бы вы поддержали в тэгах стили форматирования ячеек (excelize.Fill, excelize.Border ...)?
|
||||||
|
2. Как бы вы поддержали в тэгах кастомные стили форматирования числовых значений, те, что не входят в стандартный набор, например `0,"K"`?
|
||||||
|
3. Как мог бы выглядеть Reader, совместимый с Writer'ом, читающий строчки из excel в Go структуры и map'ы?
|
48
excelwriter/writer.go
Normal file
48
excelwriter/writer.go
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
//go:build !solution
|
||||||
|
|
||||||
|
package excelwriter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/xuri/excelize/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Writer interface {
|
||||||
|
// WriteRow appends struct fields or map values to excel sheet.
|
||||||
|
//
|
||||||
|
// Integers and floats are encoded as excel type Number.
|
||||||
|
// Strings are encoded as excel type Text.
|
||||||
|
// Booleans are encoded as excel type Logical.
|
||||||
|
//
|
||||||
|
// Pointer values are encoded as the value pointed to. A nil pointer is skipped.
|
||||||
|
//
|
||||||
|
// Values implementing encoding.TextMarshaler interface are encoded as excel Text.
|
||||||
|
//
|
||||||
|
// Interface values are encoded as the value contained in the interface. A nil interface is skipped.
|
||||||
|
//
|
||||||
|
// Channels and functions are skipped.
|
||||||
|
//
|
||||||
|
// Structs, maps, slices and arrays are marshaled into json and encoded as excel Text.
|
||||||
|
//
|
||||||
|
// Encoding of each struct field can be customized by format string
|
||||||
|
// stored under the "xlsx" key in the field's tag.
|
||||||
|
//
|
||||||
|
// // Field appears in excel under column "my_field".
|
||||||
|
// Field int `xlsx:"my_field"`
|
||||||
|
//
|
||||||
|
// // Field appears in excel under column "my_field" formatted with predeclared style 15 ("d-mmm-yy").
|
||||||
|
// // Only applicable for integers and floats.
|
||||||
|
// Field int `xlsx:"my_field,numfmt:15"`
|
||||||
|
//
|
||||||
|
// // Field is ignored by this package
|
||||||
|
// Field int `xlsx:"-"`
|
||||||
|
//
|
||||||
|
// The first row is reserved for column names.
|
||||||
|
// For structs column name must be either lowercase field name or the name from "xlsx" tag if present.
|
||||||
|
// For maps column name is a map key.
|
||||||
|
// If map key implements encoding.TextMarshaler then column name is string(key.MarshalText()).
|
||||||
|
WriteRow(r any) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(f *excelize.File) Writer {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
268
excelwriter/writer_test.go
Normal file
268
excelwriter/writer_test.go
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
package excelwriter_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/xuri/excelize/v2"
|
||||||
|
|
||||||
|
"gitlab.com/slon/shad-go/excelwriter"
|
||||||
|
)
|
||||||
|
|
||||||
|
const Sheet = "Sheet1"
|
||||||
|
|
||||||
|
type MyInt int
|
||||||
|
|
||||||
|
type Basic struct {
|
||||||
|
I int `xlsx:"i"`
|
||||||
|
UI uint `xlsx:"ui"`
|
||||||
|
I16 int16 `xlsx:"i_16"`
|
||||||
|
UI16 uint16 `xlsx:"ui_16"`
|
||||||
|
I32 int32 `xlsx:"i_32"`
|
||||||
|
UI32 uint32 `xlsx:"ui_32"`
|
||||||
|
I64 int64 `xlsx:"i_64"`
|
||||||
|
UI64 uint64 `xlsx:"ui_64"`
|
||||||
|
|
||||||
|
Float float32 `xlsx:"float"`
|
||||||
|
Double float64 `xlsx:"double"`
|
||||||
|
Bool bool `xlsx:"bool"`
|
||||||
|
String string `xlsx:"string"`
|
||||||
|
|
||||||
|
MyInt int `xlsx:"my_int"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Inner struct {
|
||||||
|
Name string `xlsx:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TextInt int
|
||||||
|
|
||||||
|
func (i TextInt) MarshalText() ([]byte, error) {
|
||||||
|
return []byte("__" + fmt.Sprint(i) + "__"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type TextStruct struct {
|
||||||
|
V string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s TextStruct) MarshalText() (text []byte, err error) {
|
||||||
|
return []byte("__" + s.V + "__"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriter_basic(t *testing.T) {
|
||||||
|
f := excelize.NewFile()
|
||||||
|
_, err := f.NewSheet(Sheet)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
w := excelwriter.New(f)
|
||||||
|
|
||||||
|
b := &Basic{
|
||||||
|
I: -1,
|
||||||
|
UI: 1,
|
||||||
|
I16: -16,
|
||||||
|
UI16: 16,
|
||||||
|
I32: -32,
|
||||||
|
UI32: 32,
|
||||||
|
I64: -64,
|
||||||
|
UI64: 64,
|
||||||
|
|
||||||
|
Float: -2.5,
|
||||||
|
Double: 5.5,
|
||||||
|
Bool: true,
|
||||||
|
String: "hello",
|
||||||
|
|
||||||
|
MyInt: 23,
|
||||||
|
}
|
||||||
|
require.NoError(t, w.WriteRow(b))
|
||||||
|
|
||||||
|
storeFile(t, f, "basic")
|
||||||
|
|
||||||
|
rows := readAll(t, f, true)
|
||||||
|
require.Equal(t, []string{"i", "ui", "i_16", "ui_16", "i_32", "ui_32", "i_64", "ui_64", "float", "double", "bool", "string", "my_int"}, rows[0])
|
||||||
|
require.Equal(t, []string{"-1", "1", "-16", "16", "-32", "32", "-64", "64", "-2.5", "5.5", "1", "hello", "23"}, rows[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriter_map(t *testing.T) {
|
||||||
|
f := excelize.NewFile()
|
||||||
|
_, err := f.NewSheet(Sheet)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
w := excelwriter.New(f)
|
||||||
|
|
||||||
|
require.NoError(t, w.WriteRow(map[string]any{
|
||||||
|
"id": 29,
|
||||||
|
"name": "hello",
|
||||||
|
"title": "yo",
|
||||||
|
}))
|
||||||
|
|
||||||
|
require.NoError(t, w.WriteRow(map[string]any{}))
|
||||||
|
|
||||||
|
require.NoError(t, w.WriteRow(map[TextStruct]any{
|
||||||
|
{"id"}: 18,
|
||||||
|
{"name"}: "tm",
|
||||||
|
}))
|
||||||
|
|
||||||
|
storeFile(t, f, "map")
|
||||||
|
|
||||||
|
rows := readAll(t, f, true)
|
||||||
|
require.Equal(t, []string{"id", "name", "title", "__id__", "__name__"}, rows[0])
|
||||||
|
require.Equal(t, []string{"29", "hello", "yo"}, rows[1])
|
||||||
|
require.Equal(t, []string{"", "", "", "18", "tm"}, rows[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
type E struct {
|
||||||
|
ID string `xlsx:"id"`
|
||||||
|
NoTag string
|
||||||
|
Skipped int `xlsx:"-"`
|
||||||
|
private float32 `xlsx:"private"`
|
||||||
|
|
||||||
|
TextInt TextInt `xlsx:"text-int"`
|
||||||
|
TextStruct TextStruct `xlsx:"text-struct"`
|
||||||
|
|
||||||
|
Struct Inner `xlsx:"inner"`
|
||||||
|
StructPtr *Inner `xlsx:"inner-ptr"`
|
||||||
|
|
||||||
|
Slice []int `xlsx:"slice"`
|
||||||
|
Array [2]int `xlsx:"arr"`
|
||||||
|
|
||||||
|
Map map[string]string `xlsx:"map"`
|
||||||
|
TMMap map[TextStruct]string `xlsx:"tm-map"`
|
||||||
|
|
||||||
|
F func() `xlsx:"func"`
|
||||||
|
Ch chan int `xlsx:"chan"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriter_elaborate(t *testing.T) {
|
||||||
|
f := excelize.NewFile()
|
||||||
|
_, err := f.NewSheet("Sheet1")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
w := excelwriter.New(f)
|
||||||
|
|
||||||
|
e := &E{
|
||||||
|
ID: "42",
|
||||||
|
NoTag: "no-tag",
|
||||||
|
Skipped: 29,
|
||||||
|
private: 2,
|
||||||
|
TextInt: 77,
|
||||||
|
TextStruct: TextStruct{V: "text-struct"},
|
||||||
|
Struct: Inner{Name: "inner"},
|
||||||
|
StructPtr: &Inner{Name: "inner-ptr"},
|
||||||
|
Slice: []int{1, 2, 3},
|
||||||
|
Array: [2]int{4, 5},
|
||||||
|
Map: map[string]string{"foo": "bar"},
|
||||||
|
TMMap: map[TextStruct]string{{"foo"}: "bar"},
|
||||||
|
F: func() { fmt.Println("hello") },
|
||||||
|
Ch: make(chan int, 10),
|
||||||
|
}
|
||||||
|
require.NoError(t, w.WriteRow(e))
|
||||||
|
|
||||||
|
storeFile(t, f, "elaborate")
|
||||||
|
|
||||||
|
rows := readAll(t, f, true)
|
||||||
|
require.Equal(t, []string{"id", "notag", "private", "text-int", "text-struct", "inner", "inner-ptr", "slice", "arr", "map", "tm-map"}, rows[0])
|
||||||
|
require.Equal(t, []string{"42", "no-tag", "2", "__77__", "__text-struct__", `{"Name":"inner"}`, `{"Name":"inner-ptr"}`, "[1,2,3]", "[4,5]", `{"foo":"bar"}`, `{"__foo__":"bar"}`}, rows[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriter_ptr(t *testing.T) {
|
||||||
|
f := excelize.NewFile()
|
||||||
|
_, err := f.NewSheet(Sheet)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
w := excelwriter.New(f)
|
||||||
|
|
||||||
|
require.NoError(t, w.WriteRow(struct{ Name string }{"foo"}))
|
||||||
|
require.NoError(t, w.WriteRow(&struct{ Name string }{"bar"}))
|
||||||
|
require.NoError(t, w.WriteRow(map[string]string{"name": "baz"}))
|
||||||
|
require.NoError(t, w.WriteRow(&map[string]string{"name": "qux"}))
|
||||||
|
|
||||||
|
storeFile(t, f, "ptr")
|
||||||
|
|
||||||
|
rows := readAll(t, f, true)
|
||||||
|
require.Equal(t, []string{"name"}, rows[0])
|
||||||
|
require.Equal(t, []string{"foo"}, rows[1])
|
||||||
|
require.Equal(t, []string{"bar"}, rows[2])
|
||||||
|
require.Equal(t, []string{"baz"}, rows[3])
|
||||||
|
require.Equal(t, []string{"qux"}, rows[4])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriter_unsupported(t *testing.T) {
|
||||||
|
f := excelize.NewFile()
|
||||||
|
_, err := f.NewSheet("Sheet1")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
w := excelwriter.New(f)
|
||||||
|
|
||||||
|
require.Error(t, w.WriteRow(2))
|
||||||
|
require.Error(t, w.WriteRow(nil))
|
||||||
|
var b *Basic
|
||||||
|
require.Error(t, w.WriteRow(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
type S struct {
|
||||||
|
P float64 `xlsx:"percent,numfmt:9"`
|
||||||
|
D int `xlsx:"date,numfmt:15"`
|
||||||
|
D2 int `xlsx:",numfmt:15"`
|
||||||
|
T float64 `xlsx:"time,numfmt:22"`
|
||||||
|
Y int `xlsx:"jpy,numfmt:194"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriter_style(t *testing.T) {
|
||||||
|
f := excelize.NewFile()
|
||||||
|
_, err := f.NewSheet("Sheet1")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
w := excelwriter.New(f)
|
||||||
|
|
||||||
|
s := &S{
|
||||||
|
P: 0.5,
|
||||||
|
D: 100,
|
||||||
|
D2: 100,
|
||||||
|
T: 100.5,
|
||||||
|
Y: 200,
|
||||||
|
}
|
||||||
|
require.NoError(t, w.WriteRow(s))
|
||||||
|
|
||||||
|
storeFile(t, f, "style")
|
||||||
|
|
||||||
|
rows := readAll(t, f, false)
|
||||||
|
require.Equal(t, []string{"percent", "date", "d2", "time", "jpy"}, rows[0])
|
||||||
|
require.Equal(t, []string{"50%", "9-Apr-00", "9-Apr-00", "4/9/00 12:00", "¥200.00"}, rows[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
func readAll(t *testing.T, f *excelize.File, raw bool) [][]string {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
var out [][]string
|
||||||
|
|
||||||
|
rows, err := f.Rows(Sheet)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var opts []excelize.Options
|
||||||
|
if raw {
|
||||||
|
opts = append(opts, excelize.Options{RawCellValue: true})
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 1; rows.Next(); i++ {
|
||||||
|
row, err := rows.Columns(opts...)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
out = append(out, row)
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func storeFile(t *testing.T, f *excelize.File, prefix string) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
out, err := os.CreateTemp("/tmp", prefix+"-*.xlsx")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = f.WriteTo(out)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Logf("stored file in %s", out.Name())
|
||||||
|
}
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -12,7 +11,7 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/tools/testtool"
|
"gitlab.com/slon/shad-go/tools/testtool"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMerge(t *testing.T) {
|
func TestMerge(t *testing.T) {
|
||||||
|
@ -33,6 +32,32 @@ func TestMerge(t *testing.T) {
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
2
|
2
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with empty lines",
|
||||||
|
in: []string{`
|
||||||
|
0`, `
|
||||||
|
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1`, `
|
||||||
|
|
||||||
|
|
||||||
|
0
|
||||||
|
2`},
|
||||||
|
out: `
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
0
|
||||||
|
0
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
|
@ -65,7 +90,7 @@ func TestSort(t *testing.T) {
|
||||||
testDir := path.Join("./testdata", "sort")
|
testDir := path.Join("./testdata", "sort")
|
||||||
|
|
||||||
readTestCase := func(dir string) (in []string, out string) {
|
readTestCase := func(dir string) (in []string, out string) {
|
||||||
files, err := ioutil.ReadDir(dir)
|
files, err := os.ReadDir(dir)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
|
@ -84,7 +109,7 @@ func TestSort(t *testing.T) {
|
||||||
testCaseDir := path.Join(testDir, d)
|
testCaseDir := path.Join(testDir, d)
|
||||||
|
|
||||||
t.Run(d, func(t *testing.T) {
|
t.Run(d, func(t *testing.T) {
|
||||||
tmpDir, err := ioutil.TempDir("", fmt.Sprintf("sort%s-", d))
|
tmpDir, err := os.MkdirTemp("", fmt.Sprintf("sort%s-", d))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer func() { _ = os.RemoveAll(tmpDir) }()
|
defer func() { _ = os.RemoveAll(tmpDir) }()
|
||||||
|
|
||||||
|
@ -95,7 +120,7 @@ func TestSort(t *testing.T) {
|
||||||
w := bufio.NewWriter(&buf)
|
w := bufio.NewWriter(&buf)
|
||||||
require.NoError(t, Sort(w, in...))
|
require.NoError(t, Sort(w, in...))
|
||||||
|
|
||||||
expected, err := ioutil.ReadFile(out)
|
expected, err := os.ReadFile(out)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.NoError(t, w.Flush())
|
require.NoError(t, w.Flush())
|
||||||
|
@ -107,7 +132,7 @@ func TestSort(t *testing.T) {
|
||||||
func listDirs(t *testing.T, dir string) []string {
|
func listDirs(t *testing.T, dir string) []string {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
files, err := ioutil.ReadDir(dir)
|
files, err := os.ReadDir(dir)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
var dirs []string
|
var dirs []string
|
||||||
|
@ -134,11 +159,11 @@ func copyFiles(t *testing.T, in []string, dir string) []string {
|
||||||
func copyFile(t *testing.T, f, dir string) string {
|
func copyFile(t *testing.T, f, dir string) string {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
data, err := ioutil.ReadFile(f)
|
data, err := os.ReadFile(f)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
dst := path.Join(dir, path.Base(f))
|
dst := path.Join(dir, path.Base(f))
|
||||||
err = ioutil.WriteFile(dst, data, 0o644)
|
err = os.WriteFile(dst, data, 0644)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
return dst
|
return dst
|
||||||
|
|
BIN
externalsort/testdata/.gitattributes
vendored
Normal file
BIN
externalsort/testdata/.gitattributes
vendored
Normal file
Binary file not shown.
|
@ -2,6 +2,61 @@
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
func main() {
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HTTPGetResult struct {
|
||||||
|
Success bool
|
||||||
|
Body string
|
||||||
|
Elapsed time.Duration
|
||||||
|
Size int
|
||||||
|
URL string
|
||||||
|
Error error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (result HTTPGetResult) String() string {
|
||||||
|
if result.Success {
|
||||||
|
return fmt.Sprintf("%v\t%v\t%v", result.Elapsed, result.Size, result.URL)
|
||||||
|
} else {
|
||||||
|
return result.Error.Error()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetHTTPBody(url string, ch chan HTTPGetResult) {
|
||||||
|
startTime := time.Now()
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
ch <- HTTPGetResult{Success: false, Error: err}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
data, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
ch <- HTTPGetResult{Success: false, Error: err}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ch <- HTTPGetResult{
|
||||||
|
Success: true,
|
||||||
|
Body: string(data),
|
||||||
|
Elapsed: time.Since(startTime),
|
||||||
|
Size: len(data),
|
||||||
|
URL: url,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
startTime := time.Now()
|
||||||
|
urls, ch := os.Args[1:], make(chan HTTPGetResult)
|
||||||
|
for _, url := range urls {
|
||||||
|
go GetHTTPBody(url, ch)
|
||||||
|
}
|
||||||
|
for i := 0; i < len(urls); i++ {
|
||||||
|
fmt.Println(<-ch)
|
||||||
|
}
|
||||||
|
fmt.Println(time.Since(startTime), "elapsed")
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,10 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/tools/testtool"
|
"gitlab.com/slon/shad-go/tools/testtool"
|
||||||
)
|
)
|
||||||
|
|
||||||
const fetchallImportPath = "gitlab.com/manytask/itmo-go/private/fetchall"
|
const fetchallImportPath = "gitlab.com/slon/shad-go/fetchall"
|
||||||
|
|
||||||
var binCache testtool.BinCache
|
var binCache testtool.BinCache
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ package fileleak_test
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
@ -11,8 +10,8 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/fileleak"
|
"gitlab.com/slon/shad-go/fileleak"
|
||||||
"gitlab.com/manytask/itmo-go/private/tools/testtool"
|
"gitlab.com/slon/shad-go/tools/testtool"
|
||||||
)
|
)
|
||||||
|
|
||||||
type fakeT struct {
|
type fakeT struct {
|
||||||
|
@ -75,7 +74,7 @@ func TestFileLeak_ReopenFile(t *testing.T) {
|
||||||
checkLeak(t, true, func() {
|
checkLeak(t, true, func() {
|
||||||
_ = f.Close()
|
_ = f.Close()
|
||||||
|
|
||||||
ff, err := ioutil.TempFile("", "")
|
ff, err := os.CreateTemp("", "")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
f = ff
|
f = ff
|
||||||
})
|
})
|
||||||
|
@ -129,6 +128,7 @@ func TestFileLeak_DupLeak(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
fd, err = syscall.Dup(1)
|
fd, err = syscall.Dup(1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
firegod/Dockerfile
Normal file
11
firegod/Dockerfile
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
FROM golang:1.22
|
||||||
|
|
||||||
|
RUN ["mkdir", "-p", "/build"]
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN ["go", "build", "-tags", "solution", "-o", "/firegod", "./firegod"]
|
||||||
|
|
||||||
|
ENTRYPOINT [ "/firegod", "-http=0.0.0.0:8080" ]
|
55
firegod/README.md
Normal file
55
firegod/README.md
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
# firegod
|
||||||
|
|
||||||
|
В этой задаче вам нужно научиться пользоваться связкой prometheus+grafana для отладки собственного кода.
|
||||||
|
|
||||||
|
Вам дан код сервиса. Нужно добавить в него метрики, и потом используя графану с помощью графиков ответить на ряд вопросов.
|
||||||
|
|
||||||
|
В этой задаче нет автоматической проверки. Чтобы получить оценку, нужно закоммитить свои ответы вместе со скриншотами в репозиторий, и поменять значение константы в `Solved` в файле `main.go` на `true`.
|
||||||
|
|
||||||
|
## Окружение
|
||||||
|
|
||||||
|
В файле `docker-compose.yaml` описан тестовый стенд.
|
||||||
|
|
||||||
|
- `prometheus` - контейнер с прометеем, который собирает метрики и выполняет запросы над ними.
|
||||||
|
- `grafana` - контейнер с графаной, дающий удобный `Web UI` для работы с прометеем.
|
||||||
|
- `my_service` - 5 реплик вашего сервиса.
|
||||||
|
|
||||||
|
Чтобы запустит тестовый стенд, выполните команду `docker compose up --build`. Чтобы перезапустить стенд, остановите `docker compose` нажав `Ctrl+C` и перезапустите команду.
|
||||||
|
|
||||||
|
После запуска стенда, проверьте что:
|
||||||
|
- [targets](http://localhost:9090/targets) показывает правильный список процессов. Один прометей в состоянии `up` и 5 копий вашего сервиса в состоянии `down` с ошибкой `server returned HTTP status 404 Not Found`.
|
||||||
|
- [grafana](http://localhost:3000/explore) пускает вас в интерфейс с логином `admin` и паролем `grafana`, а на странице Explore видно какие-то метрики (например `up`).
|
||||||
|
|
||||||
|
## Сервис
|
||||||
|
|
||||||
|
В пакете `dontlook` находится код сервиса. В него смотреть *нельзя*.
|
||||||
|
|
||||||
|
Вам нужно дописать код сбора и экспорта метрик в файл `main.go`.
|
||||||
|
|
||||||
|
1. Сделайте так, чтобы метрики экспортировались по запросу `GET /metrics`.
|
||||||
|
2. Включите экспорт метрик go рантайма и процесса (если они уже не экспортируются по дефолту).
|
||||||
|
3. Добавьте middleware записывающий метрики из http хендлеров.
|
||||||
|
|
||||||
|
## Вопросы
|
||||||
|
|
||||||
|
1. Сколько процессов каких сервисов подключено к прометею? (пример)
|
||||||
|
|
||||||
|
**Ответ**: 1 прометей и 5 моих сервисов.
|
||||||
|
|
||||||
|
![](screenshots/up.png)
|
||||||
|
|
||||||
|
2. Какой процесс постоянно перезапускается?
|
||||||
|
|
||||||
|
3. В каком процесс есть утечка файловых дескрипторов?
|
||||||
|
|
||||||
|
4. В каком процессе есть утечка памяти?
|
||||||
|
|
||||||
|
5. В каком процессе утекают горутины?
|
||||||
|
|
||||||
|
6. Какой хендлер пятисотит больше всех?
|
||||||
|
|
||||||
|
7. Сколько всего запросов в секунду приходит в сервис?
|
||||||
|
|
||||||
|
8. Какой хендлер медленнее всех отвечает, если сравнивать по 90-ой перцентиле времени ответа?
|
||||||
|
|
||||||
|
9. Какой хендлер генерирует больше всего трафика?
|
62
firegod/docker-compose.yaml
Normal file
62
firegod/docker-compose.yaml
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
services:
|
||||||
|
prometheus:
|
||||||
|
image: prom/prometheus
|
||||||
|
container_name: prometheus
|
||||||
|
command:
|
||||||
|
- '--config.file=/etc/prometheus/prometheus.yml'
|
||||||
|
ports:
|
||||||
|
- 9090:9090
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./prometheus:/etc/prometheus
|
||||||
|
|
||||||
|
grafana:
|
||||||
|
image: grafana/grafana
|
||||||
|
container_name: grafana
|
||||||
|
ports:
|
||||||
|
- 3000:3000
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- GF_SECURITY_ADMIN_USER=admin
|
||||||
|
- GF_SECURITY_ADMIN_PASSWORD=grafana
|
||||||
|
volumes:
|
||||||
|
- ./grafana:/etc/grafana/provisioning/datasources
|
||||||
|
|
||||||
|
my-service-0: &service
|
||||||
|
build:
|
||||||
|
context: ..
|
||||||
|
dockerfile: firegod/Dockerfile
|
||||||
|
restart: always
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '0.5'
|
||||||
|
memory: 100M
|
||||||
|
|
||||||
|
container_name: my-service-0
|
||||||
|
environment:
|
||||||
|
- REPLICA=0
|
||||||
|
|
||||||
|
my-service-1:
|
||||||
|
<<: *service
|
||||||
|
container_name: my-service-1
|
||||||
|
environment:
|
||||||
|
- REPLICA=1
|
||||||
|
|
||||||
|
my-service-2:
|
||||||
|
<<: *service
|
||||||
|
container_name: my-service-2
|
||||||
|
environment:
|
||||||
|
- REPLICA=2
|
||||||
|
|
||||||
|
my-service-3:
|
||||||
|
<<: *service
|
||||||
|
container_name: my-service-3
|
||||||
|
environment:
|
||||||
|
- REPLICA=3
|
||||||
|
|
||||||
|
my-service-4:
|
||||||
|
<<: *service
|
||||||
|
container_name: my-service-4
|
||||||
|
environment:
|
||||||
|
- REPLICA=4
|
111
firegod/dontlook/itoldyounottolook.go
Normal file
111
firegod/dontlook/itoldyounottolook.go
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
package dontlook
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewService(r chi.Router) {
|
||||||
|
replica := os.Getenv("REPLICA")
|
||||||
|
|
||||||
|
switch replica {
|
||||||
|
case "0":
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
go func() { select {} }()
|
||||||
|
|
||||||
|
time.Sleep(time.Millisecond * 100)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
case "2":
|
||||||
|
go func() {
|
||||||
|
var buf []string
|
||||||
|
for i := 0; true; i++ {
|
||||||
|
buf = append(buf, strings.Repeat("f", 1<<20))
|
||||||
|
_ = buf
|
||||||
|
|
||||||
|
time.Sleep(time.Millisecond * 100 * time.Duration(i))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
case "3":
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
_, _ = net.Dial("tcp", "localhost:8080")
|
||||||
|
time.Sleep(time.Millisecond * 10)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
case "4":
|
||||||
|
go func() {
|
||||||
|
time.Sleep(time.Second * 15)
|
||||||
|
os.Exit(1)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
runClient := func(getUrl func() string) {
|
||||||
|
for {
|
||||||
|
go func() {
|
||||||
|
rsp, err := http.Get(fmt.Sprintf("http://localhost:8080%s", getUrl()))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _ = io.ReadAll(rsp.Body)
|
||||||
|
_ = rsp.Body.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
time.Sleep(time.Microsecond * 100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Get("/apple", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(200)
|
||||||
|
time.Sleep(time.Millisecond * 100)
|
||||||
|
_, _ = w.Write([]byte("OK"))
|
||||||
|
})
|
||||||
|
go runClient(func() string { return "/apple" })
|
||||||
|
|
||||||
|
r.Get("/banana", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(200)
|
||||||
|
_, _ = w.Write(bytes.Repeat([]byte("f"), 1<<10))
|
||||||
|
|
||||||
|
if replica == "0" {
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
go runClient(func() string { return "/banana" })
|
||||||
|
|
||||||
|
var k atomic.Int32
|
||||||
|
r.Get("/orange", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if k.Add(1)%100 == 0 {
|
||||||
|
w.WriteHeader(500)
|
||||||
|
} else {
|
||||||
|
w.WriteHeader(200)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
go runClient(func() string { return "/orange" })
|
||||||
|
|
||||||
|
r.Get("/kiwi/{id}", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if replica == "3" {
|
||||||
|
w.WriteHeader(200)
|
||||||
|
} else {
|
||||||
|
w.WriteHeader(500)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var i atomic.Int32
|
||||||
|
go runClient(func() string { return fmt.Sprintf("/kiwi/%d", i.Add(1)) })
|
||||||
|
}
|
9
firegod/grafana/datasource.yml
Normal file
9
firegod/grafana/datasource.yml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
apiVersion: 1
|
||||||
|
|
||||||
|
datasources:
|
||||||
|
- name: Prometheus
|
||||||
|
type: prometheus
|
||||||
|
url: http://prometheus:9090
|
||||||
|
isDefault: true
|
||||||
|
access: proxy
|
||||||
|
editable: true
|
24
firegod/main.go
Normal file
24
firegod/main.go
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
"gitlab.com/slon/shad-go/firegod/dontlook"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Solved = false
|
||||||
|
|
||||||
|
var flagPort = flag.String("http", "", "")
|
||||||
|
|
||||||
|
var router = chi.NewRouter()
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
dontlook.NewService(router)
|
||||||
|
|
||||||
|
log.Fatal(http.ListenAndServe(*flagPort, router))
|
||||||
|
}
|
11
firegod/main_test.go
Normal file
11
firegod/main_test.go
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFiregod(t *testing.T) {
|
||||||
|
require.True(t, Solved)
|
||||||
|
}
|
36
firegod/prometheus/prometheus.yml
Normal file
36
firegod/prometheus/prometheus.yml
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
global:
|
||||||
|
scrape_interval: 5s
|
||||||
|
evaluation_interval: 5s
|
||||||
|
scrape_timeout: 1s
|
||||||
|
|
||||||
|
alerting:
|
||||||
|
alertmanagers:
|
||||||
|
- static_configs:
|
||||||
|
- targets: []
|
||||||
|
scheme: http
|
||||||
|
timeout: 1s
|
||||||
|
api_version: v1
|
||||||
|
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: prometheus
|
||||||
|
honor_timestamps: true
|
||||||
|
scrape_interval: 5s
|
||||||
|
scrape_timeout: 1s
|
||||||
|
metrics_path: /metrics
|
||||||
|
scheme: http
|
||||||
|
static_configs:
|
||||||
|
- targets:
|
||||||
|
- localhost:9090
|
||||||
|
- job_name: my-service
|
||||||
|
honor_timestamps: true
|
||||||
|
scrape_interval: 5s
|
||||||
|
scrape_timeout: 1s
|
||||||
|
metrics_path: /metrics
|
||||||
|
scheme: http
|
||||||
|
static_configs:
|
||||||
|
- targets:
|
||||||
|
- my-service-0:8080
|
||||||
|
- my-service-1:8080
|
||||||
|
- my-service-2:8080
|
||||||
|
- my-service-3:8080
|
||||||
|
- my-service-4:8080
|
BIN
firegod/screenshots/up.png
Normal file
BIN
firegod/screenshots/up.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 145 KiB |
|
@ -51,6 +51,6 @@ Forbidden
|
||||||
## Resources
|
## Resources
|
||||||
|
|
||||||
* project layout: https://github.com/golang-standards/project-layout
|
* project layout: https://github.com/golang-standards/project-layout
|
||||||
* reverse proxy: https://en.wikipedia.org/wiki/Reverse_proxy
|
* reverse proxy: https://pkg.go.dev/net/http/httputil#ReverseProxy
|
||||||
* yaml: https://gopkg.in/yaml.v2
|
* yaml: https://gopkg.in/yaml.v2
|
||||||
* regexp: https://golang.org/pkg/regexp/
|
* regexp: https://golang.org/pkg/regexp/
|
||||||
|
|
|
@ -3,7 +3,6 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
|
@ -15,10 +14,10 @@ import (
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/tools/testtool"
|
"gitlab.com/slon/shad-go/tools/testtool"
|
||||||
)
|
)
|
||||||
|
|
||||||
const importPath = "gitlab.com/manytask/itmo-go/private/firewall/cmd/firewall"
|
const importPath = "gitlab.com/slon/shad-go/firewall/cmd/firewall"
|
||||||
|
|
||||||
var binCache testtool.BinCache
|
var binCache testtool.BinCache
|
||||||
|
|
||||||
|
@ -36,7 +35,7 @@ func storeConfig(t *testing.T, conf string) (filename string, cleanup func()) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
filename = path.Join(os.TempDir(), testtool.RandomName()+".yaml")
|
filename = path.Join(os.TempDir(), testtool.RandomName()+".yaml")
|
||||||
err := ioutil.WriteFile(filename, []byte(conf), 0o777)
|
err := os.WriteFile(filename, []byte(conf), 0777)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
cleanup = func() { _ = os.Remove(filename) }
|
cleanup = func() { _ = os.Remove(filename) }
|
||||||
|
|
|
@ -79,6 +79,18 @@ Stack:
|
||||||
а `definition` состоит из известных слов и чисел, разделённых пробелами.
|
а `definition` состоит из известных слов и чисел, разделённых пробелами.
|
||||||
Слова можно переопределять.
|
Слова можно переопределять.
|
||||||
|
|
||||||
|
При реализации механизма определений обратите внимание на юнит-тест
|
||||||
|
|
||||||
|
```go
|
||||||
|
{
|
||||||
|
description: "no redefinition",
|
||||||
|
input: []string{": foo 5 ;", ": bar foo ;", ": foo 6 ;", "bar foo"},
|
||||||
|
expected: []int{5, 6},
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
То есть семантика слова вычисляется непосредственно при определении и не меняется при переопределении "зависимостей".
|
||||||
|
|
||||||
### Проверка решения
|
### Проверка решения
|
||||||
|
|
||||||
Для запуска тестов нужно выполнить следующую команду:
|
Для запуска тестов нужно выполнить следующую команду:
|
||||||
|
|
160
forth/eval.go
160
forth/eval.go
|
@ -2,17 +2,173 @@
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
type Evaluator struct {
|
type Evaluator struct {
|
||||||
|
stack []int
|
||||||
|
words map[string](func() error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Evaluator) push(n int) {
|
||||||
|
e.stack = append(e.stack, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Evaluator) pop() (int, error) {
|
||||||
|
size := len(e.stack)
|
||||||
|
if size == 0 {
|
||||||
|
return 0, errors.New("nothing to pop")
|
||||||
|
}
|
||||||
|
n := e.stack[size-1]
|
||||||
|
e.stack = e.stack[:size-1]
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Evaluator) popTwo() (int, int, error) {
|
||||||
|
if len(e.stack) < 2 {
|
||||||
|
return 0, 0, errors.New("not enough elements on stack")
|
||||||
|
}
|
||||||
|
second, _ := e.pop()
|
||||||
|
first, _ := e.pop()
|
||||||
|
return first, second, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used to initialzie arithemtic operations in words map
|
||||||
|
func (e *Evaluator) arithmeticOp(op func(int, int) int) func() error {
|
||||||
|
return func() error {
|
||||||
|
a, b, err := e.popTwo()
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("not enough elements on stack")
|
||||||
|
}
|
||||||
|
e.push(op(a, b))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Evaluator) initBasicWords() {
|
||||||
|
e.words["+"] = e.arithmeticOp(func(a, b int) int { return a + b })
|
||||||
|
e.words["-"] = e.arithmeticOp(func(a, b int) int { return a - b })
|
||||||
|
e.words["*"] = e.arithmeticOp(func(a, b int) int { return a * b })
|
||||||
|
e.words["/"] = func() error {
|
||||||
|
a, b, err := e.popTwo()
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("not enough elements on stack")
|
||||||
|
}
|
||||||
|
if b == 0 {
|
||||||
|
return errors.New("division by zero")
|
||||||
|
}
|
||||||
|
e.push(a / b)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
e.words["dup"] = func() error {
|
||||||
|
size := len(e.stack)
|
||||||
|
if size == 0 {
|
||||||
|
return errors.New("not enough elements on stack")
|
||||||
|
}
|
||||||
|
e.stack = append(e.stack, e.stack[size-1])
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
e.words["over"] = func() error {
|
||||||
|
size := len(e.stack)
|
||||||
|
if size < 2 {
|
||||||
|
return errors.New("not enough elements on stack")
|
||||||
|
}
|
||||||
|
e.stack = append(e.stack, e.stack[size-2])
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
e.words["drop"] = func() error {
|
||||||
|
_, err := e.pop()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
e.words["swap"] = func() error {
|
||||||
|
size := len(e.stack)
|
||||||
|
if size < 2 {
|
||||||
|
return errors.New("not enough elements on stack")
|
||||||
|
}
|
||||||
|
e.stack[size-1], e.stack[size-2] = e.stack[size-2], e.stack[size-1]
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Evaluator) getFunc(word string) (func() error, error) {
|
||||||
|
call, found := e.words[word]
|
||||||
|
if found {
|
||||||
|
return call, nil
|
||||||
|
}
|
||||||
|
num, err := strconv.Atoi(word)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("word is not numerical or is not defined")
|
||||||
|
}
|
||||||
|
call = func() error {
|
||||||
|
e.push(num)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return call, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Evaluator) defineWord(word string, def string) error {
|
||||||
|
_, err := strconv.Atoi(word)
|
||||||
|
if err == nil {
|
||||||
|
return errors.New("word definition must not be numeric")
|
||||||
|
}
|
||||||
|
definitionWords := strings.Fields(def)
|
||||||
|
callChain := make([](func() error), len(definitionWords))
|
||||||
|
for i, w := range definitionWords {
|
||||||
|
call, err := e.getFunc(w)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
callChain[i] = call
|
||||||
|
}
|
||||||
|
e.words[word] = func() error {
|
||||||
|
for _, call := range callChain {
|
||||||
|
err := call()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEvaluator creates evaluator.
|
// NewEvaluator creates evaluator.
|
||||||
func NewEvaluator() *Evaluator {
|
func NewEvaluator() *Evaluator {
|
||||||
return &Evaluator{}
|
eval := &Evaluator{make([]int, 0), make(map[string](func() error))}
|
||||||
|
eval.initBasicWords()
|
||||||
|
return eval
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process evaluates sequence of words or definition.
|
// Process evaluates sequence of words or definition.
|
||||||
//
|
//
|
||||||
// Returns resulting stack state and an error.
|
// Returns resulting stack state and an error.
|
||||||
func (e *Evaluator) Process(row string) ([]int, error) {
|
func (e *Evaluator) Process(row string) ([]int, error) {
|
||||||
return nil, nil
|
row = strings.ToLower(row)
|
||||||
|
if strings.HasPrefix(row, ":") && strings.HasSuffix(row, ";") {
|
||||||
|
row = strings.Trim(row, " :;")
|
||||||
|
wordAndDef := strings.SplitN(row, " ", 2)
|
||||||
|
if len(wordAndDef) < 2 {
|
||||||
|
return e.stack, errors.New("couldn't define a new word - incorrect syntax")
|
||||||
|
}
|
||||||
|
word, def := wordAndDef[0], wordAndDef[1]
|
||||||
|
err := e.defineWord(word, def)
|
||||||
|
if err != nil {
|
||||||
|
return e.stack, err
|
||||||
|
}
|
||||||
|
return e.stack, nil
|
||||||
|
}
|
||||||
|
for _, word := range strings.Fields(row) {
|
||||||
|
call, err := e.getFunc(word)
|
||||||
|
if err != nil {
|
||||||
|
return e.stack, err
|
||||||
|
}
|
||||||
|
err = call()
|
||||||
|
if err != nil {
|
||||||
|
return e.stack, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return e.stack, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,6 +99,11 @@ var testCases = []testCase{
|
||||||
input: []string{"2 4 * 3 /"},
|
input: []string{"2 4 * 3 /"},
|
||||||
expected: []int{2},
|
expected: []int{2},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
description: "add non-empty stack",
|
||||||
|
input: []string{"1 2 3 +"},
|
||||||
|
expected: []int{1, 5},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
description: "dup",
|
description: "dup",
|
||||||
input: []string{"1 dup"},
|
input: []string{"1 dup"},
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.uber.org/goleak"
|
"go.uber.org/goleak"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/genericsum"
|
"gitlab.com/slon/shad-go/genericsum"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMin(t *testing.T) {
|
func TestMin(t *testing.T) {
|
||||||
|
@ -184,11 +184,42 @@ func TestIsHermitianMatrix(t *testing.T) {
|
||||||
{7, 2, 12},
|
{7, 2, 12},
|
||||||
{9, 12, 19},
|
{9, 12, 19},
|
||||||
}))
|
}))
|
||||||
|
assert.True(t, genericsum.IsHermitianMatrix([][]int8{
|
||||||
|
{-1, 7, 9},
|
||||||
|
{7, -2, 12},
|
||||||
|
{9, 12, -19},
|
||||||
|
}))
|
||||||
|
assert.True(t, genericsum.IsHermitianMatrix([][]uint16{
|
||||||
|
{1, 7, 9},
|
||||||
|
{7, 2, 12},
|
||||||
|
{9, 12, 19},
|
||||||
|
}))
|
||||||
assert.False(t, genericsum.IsHermitianMatrix([][]int{
|
assert.False(t, genericsum.IsHermitianMatrix([][]int{
|
||||||
{1, 12, 8},
|
{1, 12, 8},
|
||||||
{3, 4, 7},
|
{3, 4, 7},
|
||||||
{8, 7, 11},
|
{8, 7, 11},
|
||||||
}))
|
}))
|
||||||
|
assert.False(t, genericsum.IsHermitianMatrix([][]int32{
|
||||||
|
{1, 112, 8},
|
||||||
|
{-3, 4, -7},
|
||||||
|
{8, 7, 11},
|
||||||
|
}))
|
||||||
|
assert.False(t, genericsum.IsHermitianMatrix([][]uint64{
|
||||||
|
{1, 12, 8},
|
||||||
|
{3, 4, 7},
|
||||||
|
{8, 7, 11},
|
||||||
|
}))
|
||||||
|
|
||||||
|
assert.True(t, genericsum.IsHermitianMatrix([][]float32{
|
||||||
|
{1.0, 7.0, 9.0},
|
||||||
|
{7.0, 2.0, 12.0},
|
||||||
|
{9.0, 12.0, 19.0},
|
||||||
|
}))
|
||||||
|
assert.False(t, genericsum.IsHermitianMatrix([][]float32{
|
||||||
|
{1.0, 12.0, 8.0},
|
||||||
|
{3.0, 4.0, 7.0},
|
||||||
|
{8.0, 7.0, 11.0},
|
||||||
|
}))
|
||||||
assert.True(t, genericsum.IsHermitianMatrix([][]complex64{
|
assert.True(t, genericsum.IsHermitianMatrix([][]complex64{
|
||||||
{1, 3 + 2i},
|
{1, 3 + 2i},
|
||||||
{3 - 2i, 4},
|
{3 - 2i, 4},
|
||||||
|
|
|
@ -175,6 +175,11 @@ export PATH=$GOPATH/bin:$PATH
|
||||||
|
|
||||||
После этого `gitfame` будет доступен всюду.
|
После этого `gitfame` будет доступен всюду.
|
||||||
|
|
||||||
|
В реализации вы можете использовать сторонние библиотеки, которые уже доступны в нашем [`go.mod`](../go.mod). Менять `go.mod` нельзя.
|
||||||
|
|
||||||
|
Весь репозиторий курса - это один go модуль с одним go.mod файлом в корне. Корню репозитория соответствует импорт путь `gitlab.com/slon/shad-go`. Если вы создадите пакет в директории `gitfame/internal/git`, то импортировать его нужно будет по пути `gitlab.com/slon/shad-go/gitfame/internal/git`.
|
||||||
|
|
||||||
|
|
||||||
### Code review comments
|
### Code review comments
|
||||||
|
|
||||||
Прочитайте и исправьте [распространённые ошибки](../docs/gitfame_review_comments.md).
|
Прочитайте и исправьте [распространённые ошибки](../docs/gitfame_review_comments.md).
|
||||||
|
|
|
@ -2,7 +2,6 @@ package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
|
@ -14,10 +13,10 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/tools/testtool"
|
"gitlab.com/slon/shad-go/tools/testtool"
|
||||||
)
|
)
|
||||||
|
|
||||||
const importPath = "gitlab.com/manytask/itmo-go/private/gitfame/cmd/gitfame"
|
const importPath = "gitlab.com/slon/shad-go/gitfame/cmd/gitfame"
|
||||||
|
|
||||||
var binCache testtool.BinCache
|
var binCache testtool.BinCache
|
||||||
|
|
||||||
|
@ -43,7 +42,7 @@ func TestGitFame(t *testing.T) {
|
||||||
tc := ReadTestCase(t, filepath.Join(testsDir, dir))
|
tc := ReadTestCase(t, filepath.Join(testsDir, dir))
|
||||||
|
|
||||||
t.Run(dir+"/"+tc.Name, func(t *testing.T) {
|
t.Run(dir+"/"+tc.Name, func(t *testing.T) {
|
||||||
dir, err := ioutil.TempDir("", "gitfame-")
|
dir, err := os.MkdirTemp("", "gitfame-")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer func() { _ = os.RemoveAll(dir) }()
|
defer func() { _ = os.RemoveAll(dir) }()
|
||||||
|
|
||||||
|
@ -75,7 +74,7 @@ func TestGitFame(t *testing.T) {
|
||||||
func ListTestDirs(t *testing.T, path string) []string {
|
func ListTestDirs(t *testing.T, path string) []string {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
files, err := ioutil.ReadDir(path)
|
files, err := os.ReadDir(path)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
var names []string
|
var names []string
|
||||||
|
@ -109,7 +108,7 @@ func ReadTestCase(t *testing.T, path string) *TestCase {
|
||||||
|
|
||||||
desc := ReadTestDescription(t, path)
|
desc := ReadTestDescription(t, path)
|
||||||
|
|
||||||
expected, err := ioutil.ReadFile(filepath.Join(path, "expected.out"))
|
expected, err := os.ReadFile(filepath.Join(path, "expected.out"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
return &TestCase{TestDescription: desc, Expected: expected}
|
return &TestCase{TestDescription: desc, Expected: expected}
|
||||||
|
@ -126,7 +125,7 @@ type TestDescription struct {
|
||||||
func ReadTestDescription(t *testing.T, path string) *TestDescription {
|
func ReadTestDescription(t *testing.T, path string) *TestDescription {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
data, err := ioutil.ReadFile(filepath.Join(path, "description.yaml"))
|
data, err := os.ReadFile(filepath.Join(path, "description.yaml"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
var desc TestDescription
|
var desc TestDescription
|
||||||
|
|
84
go.mod
84
go.mod
|
@ -1,66 +1,80 @@
|
||||||
module gitlab.com/manytask/itmo-go/private
|
module gitlab.com/slon/shad-go
|
||||||
|
|
||||||
go 1.18
|
go 1.22.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/felixge/httpsnoop v1.0.3
|
github.com/felixge/httpsnoop v1.0.3
|
||||||
github.com/go-chi/chi/v5 v5.0.8
|
github.com/go-chi/chi/v5 v5.0.8
|
||||||
|
github.com/go-git/go-git/v5 v5.11.0
|
||||||
github.com/go-redis/redis/v8 v8.11.5
|
github.com/go-redis/redis/v8 v8.11.5
|
||||||
github.com/go-resty/resty/v2 v2.1.0
|
github.com/go-resty/resty/v2 v2.1.0
|
||||||
github.com/gofrs/uuid v3.3.0+incompatible
|
github.com/gofrs/uuid v3.3.0+incompatible
|
||||||
github.com/golang/mock v1.4.1
|
github.com/golang/mock v1.6.0
|
||||||
github.com/google/go-cmp v0.5.9
|
github.com/google/btree v1.1.2
|
||||||
|
github.com/google/go-cmp v0.6.0
|
||||||
github.com/gorilla/handlers v1.4.2
|
github.com/gorilla/handlers v1.4.2
|
||||||
github.com/gorilla/mux v1.7.4
|
github.com/gorilla/mux v1.7.4
|
||||||
github.com/gorilla/websocket v1.4.2
|
github.com/gorilla/websocket v1.4.2
|
||||||
github.com/jackc/pgx/v4 v4.6.0
|
github.com/jackc/pgx/v5 v5.5.3
|
||||||
github.com/jonboulle/clockwork v0.1.0
|
github.com/jonboulle/clockwork v0.4.0
|
||||||
github.com/spf13/cobra v1.1.3
|
github.com/spf13/cobra v1.1.3
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/stretchr/testify v1.8.2
|
github.com/stretchr/testify v1.8.4
|
||||||
go.uber.org/goleak v1.0.0
|
go.uber.org/goleak v1.3.0
|
||||||
go.uber.org/zap v1.14.0
|
go.uber.org/zap v1.26.0
|
||||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29
|
golang.org/x/exp v0.0.0-20230321023759-10a507213a29
|
||||||
golang.org/x/perf v0.0.0-20191209155426-36b577b0eb03
|
golang.org/x/perf v0.0.0-20191209155426-36b577b0eb03
|
||||||
golang.org/x/sync v0.1.0
|
golang.org/x/sync v0.6.0
|
||||||
golang.org/x/sys v0.7.0
|
golang.org/x/sys v0.17.0
|
||||||
golang.org/x/tools v0.7.0
|
golang.org/x/tools v0.18.0
|
||||||
google.golang.org/grpc v1.54.0
|
google.golang.org/grpc v1.54.0
|
||||||
google.golang.org/protobuf v1.30.0
|
google.golang.org/protobuf v1.33.0
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/BurntSushi/toml v0.3.1 // indirect
|
dario.cat/mergo v1.0.0 // indirect
|
||||||
|
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||||
|
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
|
||||||
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
|
github.com/cloudflare/circl v1.3.3 // indirect
|
||||||
|
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
|
github.com/emirpasic/gods v1.18.1 // indirect
|
||||||
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||||
|
github.com/go-git/go-billy/v5 v5.5.0 // indirect
|
||||||
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/golang/protobuf v1.5.3 // indirect
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||||
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
|
|
||||||
github.com/jackc/pgconn v1.5.0 // indirect
|
|
||||||
github.com/jackc/pgio v1.0.0 // indirect
|
|
||||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
github.com/jackc/pgproto3/v2 v2.0.1 // indirect
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||||
github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8 // indirect
|
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||||
github.com/jackc/pgtype v1.3.0 // indirect
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||||
github.com/kr/pretty v0.3.0 // indirect
|
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||||
github.com/lib/pq v1.10.0 // indirect
|
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.8.0 // indirect
|
github.com/prometheus/client_golang v1.19.1 // indirect
|
||||||
|
github.com/prometheus/client_model v0.5.0 // indirect
|
||||||
|
github.com/prometheus/common v0.48.0 // indirect
|
||||||
|
github.com/prometheus/procfs v0.12.0 // indirect
|
||||||
|
github.com/richardlehane/mscfb v1.0.4 // indirect
|
||||||
|
github.com/richardlehane/msoleps v1.0.3 // indirect
|
||||||
|
github.com/sergi/go-diff v1.1.0 // indirect
|
||||||
|
github.com/skeema/knownhosts v1.2.1 // indirect
|
||||||
github.com/stretchr/objx v0.5.0 // indirect
|
github.com/stretchr/objx v0.5.0 // indirect
|
||||||
go.uber.org/atomic v1.5.0 // indirect
|
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||||
go.uber.org/multierr v1.3.0 // indirect
|
github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 // indirect
|
||||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee // indirect
|
github.com/xuri/excelize/v2 v2.8.1 // indirect
|
||||||
golang.org/x/crypto v0.5.0 // indirect
|
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 // indirect
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de // indirect
|
go.uber.org/multierr v1.10.0 // indirect
|
||||||
golang.org/x/mod v0.9.0 // indirect
|
golang.org/x/crypto v0.19.0 // indirect
|
||||||
golang.org/x/net v0.9.0 // indirect
|
golang.org/x/mod v0.15.0 // indirect
|
||||||
golang.org/x/text v0.9.0 // indirect
|
golang.org/x/net v0.21.0 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
|
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3 // indirect
|
|
||||||
)
|
)
|
||||||
|
|
301
go.sum
301
go.sum
|
@ -11,38 +11,50 @@ cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7
|
||||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||||
|
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||||
|
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20190129172621-c8b1d7a94ddf/go.mod h1:aJ4qN3TfrelA6NZ6AXsXRfmEVaYin3EDbSPJrKS8OXo=
|
github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20190129172621-c8b1d7a94ddf/go.mod h1:aJ4qN3TfrelA6NZ6AXsXRfmEVaYin3EDbSPJrKS8OXo=
|
||||||
|
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||||
|
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||||
|
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
|
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg=
|
||||||
|
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||||
github.com/aclements/go-gg v0.0.0-20170118225347-6dbb4e4fefb0/go.mod h1:55qNq4vcpkIuHowELi5C8e+1yUHtoLoOUR9QU5j7Tes=
|
github.com/aclements/go-gg v0.0.0-20170118225347-6dbb4e4fefb0/go.mod h1:55qNq4vcpkIuHowELi5C8e+1yUHtoLoOUR9QU5j7Tes=
|
||||||
github.com/aclements/go-moremath v0.0.0-20161014184102-0ff62e0875ff/go.mod h1:idZL3yvz4kzx1dsBOAC+oYv6L92P1oFEhUXUB1A/lwQ=
|
github.com/aclements/go-moremath v0.0.0-20161014184102-0ff62e0875ff/go.mod h1:idZL3yvz4kzx1dsBOAC+oYv6L92P1oFEhUXUB1A/lwQ=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||||
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||||
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||||
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||||
|
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
|
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
|
||||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
|
||||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
@ -50,14 +62,29 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
|
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
|
||||||
|
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||||
|
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||||
|
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
||||||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
||||||
|
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
|
||||||
github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0=
|
github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0=
|
||||||
github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||||
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||||
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||||
|
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
|
||||||
|
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
|
||||||
|
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||||
|
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||||
|
github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4=
|
||||||
|
github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
|
@ -68,18 +95,19 @@ github.com/go-resty/resty/v2 v2.1.0 h1:Z6IefCpUMfnvItVJaJXWv/pMiiD11So35QgwEELsl
|
||||||
github.com/go-resty/resty/v2 v2.1.0/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8=
|
github.com/go-resty/resty/v2 v2.1.0/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8=
|
||||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
|
||||||
github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84=
|
github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84=
|
||||||
github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||||
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
github.com/golang/mock v1.4.1 h1:ocYkMQY5RrXTYgXl7ICpV0IXwlEQGwKIsery4gyXa1U=
|
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
@ -93,11 +121,13 @@ github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2
|
||||||
github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw=
|
github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||||
|
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
@ -137,78 +167,39 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
|
||||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
|
|
||||||
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
|
||||||
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
|
|
||||||
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
|
||||||
github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA=
|
|
||||||
github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE=
|
|
||||||
github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s=
|
|
||||||
github.com/jackc/pgconn v1.5.0 h1:oFSOilzIZkyg787M1fEmyMfOUUvwj0daqYMfaWwNL4o=
|
|
||||||
github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI=
|
|
||||||
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
|
|
||||||
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
|
|
||||||
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye4717ITLaNwV9mWbJx0dLCpcRzdA=
|
|
||||||
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
|
|
||||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||||
github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78=
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA=
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
|
github.com/jackc/pgx/v5 v5.5.3 h1:Ces6/M3wbDXYpM8JyyPD57ivTtJACFZJd885pdIaV2s=
|
||||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
github.com/jackc/pgx/v5 v5.5.3/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||||
github.com/jackc/pgproto3/v2 v2.0.1 h1:Rdjp4NFjwHnEslx2b66FfCI2S0LhO4itac3hXz6WX9M=
|
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||||
github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||||
github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8 h1:Q3tB+ExeflWUW7AFcAhXqk40s9mnNYLk1nOkKNZ5GnU=
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||||
github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
|
|
||||||
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
|
|
||||||
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
|
|
||||||
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
|
|
||||||
github.com/jackc/pgtype v1.3.0 h1:l8JvKrby3RI7Kg3bYEeU9TA4vqC38QDpFCfcrC7KuN0=
|
|
||||||
github.com/jackc/pgtype v1.3.0/go.mod h1:b0JqxHvPmljG+HQ5IsvQ0yqeSi4nGcDTVjFoiLDb0Ik=
|
|
||||||
github.com/jackc/pgx v3.6.2+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
|
|
||||||
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
|
|
||||||
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
|
|
||||||
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
|
|
||||||
github.com/jackc/pgx/v4 v4.6.0 h1:Fh0O9GdlG4gYpjpwOqjdEodJUQM9jzN3Hdv7PN0xmm0=
|
|
||||||
github.com/jackc/pgx/v4 v4.6.0/go.mod h1:vPh43ZzxijXUVJ+t/EmXBtFmbFVO72cuneCT9oAlxAg=
|
|
||||||
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
|
||||||
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
|
||||||
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
|
||||||
github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
|
|
||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
|
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
|
||||||
|
github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
|
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||||
|
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
|
||||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
|
||||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
|
||||||
github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E=
|
|
||||||
github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
|
||||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
|
||||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
|
||||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
|
||||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
|
||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
|
||||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
|
||||||
github.com/mattn/go-sqlite3 v0.0.0-20161215041557-2d44decb4941/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v0.0.0-20161215041557-2d44decb4941/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||||
|
@ -222,14 +213,20 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
|
||||||
|
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||||
|
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||||
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
|
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||||
|
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||||
|
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
|
||||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||||
|
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
@ -239,31 +236,40 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||||
|
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
|
||||||
|
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
|
||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||||
|
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
|
github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
|
||||||
|
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
|
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||||
|
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
|
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
|
||||||
|
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
|
||||||
|
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||||
|
github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM=
|
||||||
|
github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||||
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
|
||||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
|
||||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
|
||||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
|
||||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 h1:pntxY8Ary0t43dCZ5dqY4YTJCObLY1kIXl0uzMv+7DE=
|
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ=
|
||||||
|
github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
|
@ -279,50 +285,54 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
|
||||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
|
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||||
|
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 h1:Chd9DkqERQQuHpXjR/HSV1jLZA6uaoiwwH3vSuF3IW0=
|
||||||
|
github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
|
||||||
|
github.com/xuri/excelize/v2 v2.8.1 h1:pZLMEwK8ep+CLIUWpWmvW8IWE/yxqG0I1xcN6cVMGuQ=
|
||||||
|
github.com/xuri/excelize/v2 v2.8.1/go.mod h1:oli1E4C3Pa5RXg1TBXn4ENCXDV5JUMlBluUhG7c+CEE=
|
||||||
|
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 h1:qhbILQo1K3mphbwKh1vNm4oGezE1eF9fQWmNiIpSfI4=
|
||||||
|
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
|
||||||
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
go.uber.org/goleak v1.0.0 h1:qsup4IcBdlmsnGfqyLl4Ntn3C2XCCuKAE7DwHpScyUo=
|
|
||||||
go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
|
||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc=
|
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
|
||||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
|
|
||||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
|
||||||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
|
||||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
go.uber.org/zap v1.14.0 h1:/pduUoebOeeJzTDFuoMgC6nRkiasr1sBCIEorly7m4o=
|
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
||||||
go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||||
|
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||||
|
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
||||||
|
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
|
@ -338,14 +348,16 @@ golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTk
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
|
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||||
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
|
||||||
|
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
@ -361,9 +373,15 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||||
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||||
|
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||||
|
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||||
golang.org/x/oauth2 v0.0.0-20170207211851-4464e7848382/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20170207211851-4464e7848382/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
@ -375,8 +393,11 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||||
|
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
@ -384,25 +405,46 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||||
|
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||||
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||||
|
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
|
||||||
|
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
@ -414,26 +456,23 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3
|
||||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
|
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
|
||||||
|
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/api v0.0.0-20170206182103-3d017632ea10/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
google.golang.org/api v0.0.0-20170206182103-3d017632ea10/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||||
|
@ -466,16 +505,21 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
|
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||||
|
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
|
||||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
|
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||||
|
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
@ -488,8 +532,5 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
|
||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ package gossip
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/gossip/meshpb"
|
"gitlab.com/slon/shad-go/gossip/meshpb"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"gitlab.com/manytask/itmo-go/private/gossip"
|
"gitlab.com/slon/shad-go/gossip"
|
||||||
"gitlab.com/manytask/itmo-go/private/gossip/meshpb"
|
"gitlab.com/slon/shad-go/gossip/meshpb"
|
||||||
"go.uber.org/goleak"
|
"go.uber.org/goleak"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
option go_package = "gitlab.com/manytask/itmo-go/private/gossip/meshpb";
|
option go_package = "gitlab.com/slon/shad-go/gossip/meshpb";
|
||||||
|
|
||||||
// PeerMeta is arbitrary message that is propagated with peer gossip.
|
// PeerMeta is arbitrary message that is propagated with peer gossip.
|
||||||
message PeerMeta {
|
message PeerMeta {
|
||||||
|
|
|
@ -6,14 +6,14 @@
|
||||||
```
|
```
|
||||||
goos: linux
|
goos: linux
|
||||||
goarch: amd64
|
goarch: amd64
|
||||||
pkg: gitlab.com/manytask/itmo-go/private/gzep
|
pkg: gitlab.com/slon/shad-go/gzep
|
||||||
cpu: Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz
|
cpu: Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz
|
||||||
BenchmarkEncodeSimple
|
BenchmarkEncodeSimple
|
||||||
BenchmarkEncodeSimple-8 7047 176628 ns/op 813872 B/op 17 allocs/op
|
BenchmarkEncodeSimple-8 7047 176628 ns/op 813872 B/op 17 allocs/op
|
||||||
BenchmarkEncode
|
BenchmarkEncode
|
||||||
BenchmarkEncode-8 41706 32616 ns/op 19 B/op 0 allocs/op
|
BenchmarkEncode-8 41706 32616 ns/op 19 B/op 0 allocs/op
|
||||||
PASS
|
PASS
|
||||||
ok gitlab.com/manytask/itmo-go/private/gzep 3.625s
|
ok gitlab.com/slon/shad-go/gzep 3.625s
|
||||||
```
|
```
|
||||||
|
|
||||||
### С чего начать?
|
### С чего начать?
|
||||||
|
|
|
@ -9,8 +9,8 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/gzep"
|
"gitlab.com/slon/shad-go/gzep"
|
||||||
"gitlab.com/manytask/itmo-go/private/tools/testtool"
|
"gitlab.com/slon/shad-go/tools/testtool"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BenchmarkEncode(b *testing.B) {
|
func BenchmarkEncode(b *testing.B) {
|
||||||
|
@ -47,6 +47,7 @@ func TestEncode_RoundTrip(t *testing.T) {
|
||||||
require.NoError(t, err, tc.in)
|
require.NoError(t, err, tc.in)
|
||||||
require.Equal(t, tc.in, string(out))
|
require.Equal(t, tc.in, string(out))
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,39 @@
|
||||||
|
|
||||||
package hogwarts
|
package hogwarts
|
||||||
|
|
||||||
func GetCourseList(prereqs map[string][]string) []string {
|
import (
|
||||||
return []string{}
|
"log"
|
||||||
|
"slices"
|
||||||
|
)
|
||||||
|
|
||||||
|
func singleCourseList(
|
||||||
|
course string, prereqs map[string][]string, list []string, traversed []string,
|
||||||
|
) []string {
|
||||||
|
if slices.Contains(traversed, course) {
|
||||||
|
log.Panic("Recursive prereqs, aborting...")
|
||||||
|
}
|
||||||
|
traversed = append(traversed, course)
|
||||||
|
for _, prereqCourse := range prereqs[course] {
|
||||||
|
if !slices.Contains(list, prereqCourse) {
|
||||||
|
i := slices.Index(list, course)
|
||||||
|
if i == -1 {
|
||||||
|
list = append(list, prereqCourse)
|
||||||
|
} else {
|
||||||
|
list = slices.Insert(list, i, prereqCourse)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list = singleCourseList(prereqCourse, prereqs, list, traversed)
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCourseList(prereqs map[string][]string) []string {
|
||||||
|
list := make([]string, 0)
|
||||||
|
for course := range prereqs {
|
||||||
|
if !slices.Contains(list, course) {
|
||||||
|
list = append(list, course)
|
||||||
|
}
|
||||||
|
list = singleCourseList(course, prereqs, list, []string{})
|
||||||
|
}
|
||||||
|
return list
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
package hotelbusiness
|
package hotelbusiness
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
type Guest struct {
|
type Guest struct {
|
||||||
CheckInDate int
|
CheckInDate int
|
||||||
CheckOutDate int
|
CheckOutDate int
|
||||||
|
@ -13,5 +15,30 @@ type Load struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ComputeLoad(guests []Guest) []Load {
|
func ComputeLoad(guests []Guest) []Load {
|
||||||
|
if len(guests) == 0 {
|
||||||
return []Load{}
|
return []Load{}
|
||||||
}
|
}
|
||||||
|
minDate, maxDate := math.MaxInt, math.MinInt
|
||||||
|
loadsNoEmptyDays := make(map[int]int)
|
||||||
|
for _, guest := range guests {
|
||||||
|
if guest.CheckInDate < minDate {
|
||||||
|
minDate = guest.CheckInDate
|
||||||
|
}
|
||||||
|
if guest.CheckOutDate > maxDate {
|
||||||
|
maxDate = guest.CheckOutDate
|
||||||
|
}
|
||||||
|
for i := guest.CheckInDate; i < guest.CheckOutDate; i++ {
|
||||||
|
loadsNoEmptyDays[i]++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loads, prevGuestCount := make([]Load, 0), 0
|
||||||
|
for i := minDate; i <= maxDate; i++ {
|
||||||
|
guestCount := loadsNoEmptyDays[i]
|
||||||
|
if prevGuestCount == guestCount {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
loads = append(loads, Load{i, guestCount})
|
||||||
|
prevGuestCount = guestCount
|
||||||
|
}
|
||||||
|
return loads
|
||||||
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/illegal"
|
"gitlab.com/slon/shad-go/illegal"
|
||||||
"gitlab.com/manytask/itmo-go/private/illegal/internal"
|
"gitlab.com/slon/shad-go/illegal/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIllegalField(t *testing.T) {
|
func TestIllegalField(t *testing.T) {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/illegal"
|
"gitlab.com/slon/shad-go/illegal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestStringFromBytes(t *testing.T) {
|
func TestStringFromBytes(t *testing.T) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/iprange"
|
"gitlab.com/slon/shad-go/iprange"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ExampleParseList() {
|
func ExampleParseList() {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
В обычном `sync.Mutex` лок всего один. В один момент времени этот лок может находиться
|
В обычном `sync.Mutex` лок всего один. В один момент времени этот лок может находиться
|
||||||
у одной горутины. В нашем примитиве локов может быть сколько угодно. Каждый лок мы идентифицируем
|
у одной горутины. В нашем примитиве локов может быть сколько угодно. Каждый лок мы идентифицируем
|
||||||
ключём - строкой. Каждая горутина приходит к нам со списком ключей и хочет захватить сразу
|
ключом - строкой. Каждая горутина приходит к нам со списком ключей и хочет захватить сразу
|
||||||
все локи из этого списка. (Наша аналогия с `sync.Mutex` вовсе не значит, что нужно использовать
|
все локи из этого списка. (Наша аналогия с `sync.Mutex` вовсе не значит, что нужно использовать
|
||||||
`sync.Mutex` в реализации. Лучше использовать каналы, чтобы проще было реализовать отмену.)
|
`sync.Mutex` в реализации. Лучше использовать каналы, чтобы проще было реализовать отмену.)
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,19 @@
|
||||||
package keylock_test
|
package keylock_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"slices"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.uber.org/goleak"
|
"go.uber.org/goleak"
|
||||||
|
|
||||||
"gitlab.com/manytask/itmo-go/private/keylock"
|
"gitlab.com/slon/shad-go/keylock"
|
||||||
|
"gitlab.com/slon/shad-go/tools/testtool"
|
||||||
)
|
)
|
||||||
|
|
||||||
func timeout(d time.Duration) <-chan struct{} {
|
func timeout(d time.Duration) <-chan struct{} {
|
||||||
|
@ -57,6 +62,21 @@ func TestKeyLock_Progress(t *testing.T) {
|
||||||
unlock1()
|
unlock1()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestKeyLock_NoBusyWait(t *testing.T) {
|
||||||
|
defer goleak.VerifyNone(t)
|
||||||
|
l := keylock.New()
|
||||||
|
|
||||||
|
_, unlock0 := l.LockKeys([]string{"a", "b"}, nil)
|
||||||
|
defer unlock0()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
_, unlock := l.LockKeys([]string{"b", "c"}, nil)
|
||||||
|
unlock()
|
||||||
|
}()
|
||||||
|
|
||||||
|
testtool.VerifyNoBusyGoroutines(t)
|
||||||
|
}
|
||||||
|
|
||||||
func TestKeyLock_DeadlockFree(t *testing.T) {
|
func TestKeyLock_DeadlockFree(t *testing.T) {
|
||||||
const N = 10000
|
const N = 10000
|
||||||
|
|
||||||
|
@ -116,7 +136,7 @@ func TestKeyLock_SingleKeyStress(t *testing.T) {
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
for i := 0; i < N; i++ {
|
for j := 0; j < N; j++ {
|
||||||
cancelled, unlock := l.LockKeys([]string{"a"}, timeout(time.Millisecond))
|
cancelled, unlock := l.LockKeys([]string{"a"}, timeout(time.Millisecond))
|
||||||
if !cancelled {
|
if !cancelled {
|
||||||
unlock()
|
unlock()
|
||||||
|
@ -127,3 +147,58 @@ func TestKeyLock_SingleKeyStress(t *testing.T) {
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestKeyLock_MutualExclusionStress(t *testing.T) {
|
||||||
|
const (
|
||||||
|
N = 1000
|
||||||
|
G = 100
|
||||||
|
M = 15
|
||||||
|
K = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
defer goleak.VerifyNone(t)
|
||||||
|
|
||||||
|
locked := map[string]bool{}
|
||||||
|
var mu sync.Mutex
|
||||||
|
|
||||||
|
l := keylock.New()
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(G)
|
||||||
|
|
||||||
|
for i := 0; i < G; i++ {
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
for j := 0; j < N; j++ {
|
||||||
|
keys := []string{}
|
||||||
|
for k := 0; k < K; k++ {
|
||||||
|
keys = append(keys, fmt.Sprint(rand.Intn(N)))
|
||||||
|
}
|
||||||
|
|
||||||
|
slices.Sort(keys)
|
||||||
|
keys = slices.Compact(keys)
|
||||||
|
|
||||||
|
_, unlock := l.LockKeys(keys, nil)
|
||||||
|
mu.Lock()
|
||||||
|
for _, key := range keys {
|
||||||
|
assert.False(t, locked[key])
|
||||||
|
locked[key] = true
|
||||||
|
}
|
||||||
|
mu.Unlock()
|
||||||
|
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
|
|
||||||
|
mu.Lock()
|
||||||
|
for _, key := range keys {
|
||||||
|
locked[key] = false
|
||||||
|
}
|
||||||
|
mu.Unlock()
|
||||||
|
|
||||||
|
unlock()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
|
@ -3,23 +3,9 @@ package keylock
|
||||||
import (
|
import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BenchmarkMutex_Baseline(b *testing.B) {
|
|
||||||
var mu sync.Mutex
|
|
||||||
|
|
||||||
b.ReportAllocs()
|
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
|
||||||
for pb.Next() {
|
|
||||||
mu.Lock()
|
|
||||||
_ = 0
|
|
||||||
mu.Unlock()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkKeyLock_SingleKey(b *testing.B) {
|
func BenchmarkKeyLock_SingleKey(b *testing.B) {
|
||||||
l := New()
|
l := New()
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
@ -30,7 +29,7 @@ func fetch(url string, ch chan<- string) {
|
||||||
}
|
}
|
||||||
defer resp.Body.Close() // don't leak resources
|
defer resp.Body.Close() // don't leak resources
|
||||||
|
|
||||||
nbytes, err := io.Copy(ioutil.Discard, resp.Body)
|
nbytes, err := io.Copy(io.Discard, resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ch <- fmt.Sprintf("while reading %s: %v", url, err)
|
ch <- fmt.Sprintf("while reading %s: %v", url, err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -11,8 +11,7 @@
|
||||||
|
|
||||||
* Ссылки
|
* Ссылки
|
||||||
|
|
||||||
.link https://wiki.yandex.ru/shad/groups/2018/Semester4/GoLang/ Вики страница
|
.link https://github.com/slon/shad-go Репозиторий
|
||||||
.link https://gitlab.com/manytask/itmo-go/private Репозиторий
|
|
||||||
.link https://t.me/joinchat/BjrYSxdPJGtJdd1pae08Zg Чат курса в телеграме
|
.link https://t.me/joinchat/BjrYSxdPJGtJdd1pae08Zg Чат курса в телеграме
|
||||||
[[https://p.go.manytask.org]] - эти слайды.
|
[[https://p.go.manytask.org]] - эти слайды.
|
||||||
|
|
||||||
|
@ -21,7 +20,7 @@
|
||||||
- 12+ занятий
|
- 12+ занятий
|
||||||
- Семинарские задания после каждой лекции. *Дедлайн*10*дней.*
|
- Семинарские задания после каждой лекции. *Дедлайн*10*дней.*
|
||||||
- 4 _больших_ домашних задания. *Дедлайн*3*недели.*
|
- 4 _больших_ домашних задания. *Дедлайн*3*недели.*
|
||||||
- Критерий оценки: *TODO*.
|
- Критерий оценки: *В*LMS* (>N домашек и >X% за семинары).
|
||||||
|
|
||||||
* Hello world
|
* Hello world
|
||||||
|
|
||||||
|
@ -37,12 +36,25 @@ Systems
|
||||||
|
|
||||||
Language
|
Language
|
||||||
|
|
||||||
|
* История
|
||||||
|
|
||||||
|
- 2009 go public announcement
|
||||||
|
- 2012 go 1.0
|
||||||
|
- 2008 github launch
|
||||||
|
- 2011 C++11
|
||||||
|
- 2011 pip initial release
|
||||||
|
- 2010 npm first release
|
||||||
|
- 2009 nodejs first release
|
||||||
|
- 2008 python3
|
||||||
|
- 2006 rust project started
|
||||||
|
- 2015 rust 1.0
|
||||||
|
|
||||||
* Современный мир
|
* Современный мир
|
||||||
|
|
||||||
- Море библиотек. Большие деревья зависимостей.
|
- Море библиотек. Большие деревья зависимостей.
|
||||||
: Нам нужен язык, который будет помогать контролировать сложность at large.
|
: Нам нужен язык, который будет помогать контролировать сложность at large.
|
||||||
- Архитектура построена вокруг сервисов, которые общаются по сети.
|
- Архитектура построена вокруг сервисов, которые общаются по сети.
|
||||||
: Скорее вам придётся писать stateless сервис. Statefull сервисы общаются с базой данных по сети.
|
: Скорее вам придётся писать stateless сервис. Stateful сервисы общаются с базой данных по сети.
|
||||||
- Многоядерные процессоры даже в телефонах.
|
- Многоядерные процессоры даже в телефонах.
|
||||||
|
|
||||||
* Скорость разработки
|
* Скорость разработки
|
||||||
|
@ -149,6 +161,8 @@ Language
|
||||||
var s = ""
|
var s = ""
|
||||||
var s string = ""
|
var s string = ""
|
||||||
|
|
||||||
|
.link https://go.dev/blog/declaration-syntax Почему тип пишется после названия переменной
|
||||||
|
|
||||||
* uniq
|
* uniq
|
||||||
|
|
||||||
.play -edit uniq/uniq.go
|
.play -edit uniq/uniq.go
|
||||||
|
@ -230,7 +244,7 @@ Pointers
|
||||||
|
|
||||||
var s string
|
var s string
|
||||||
p := &s
|
p := &s
|
||||||
s2 = *p
|
s2 := *p
|
||||||
|
|
||||||
var p Point
|
var p Point
|
||||||
p.X = 1
|
p.X = 1
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue