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/
|
||||
|
||||
/example/
|
||||
|
||||
# Go profiling files
|
||||
*.out
|
||||
*.test
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
grade:
|
||||
image: cr.yandex/crp9onavos88ug32d5r2/grader/go
|
||||
variables:
|
||||
DOCKER_HOST: tcp://docker:2375/
|
||||
DOCKER_TLS_CERTDIR: ""
|
||||
APP_HOST: docker
|
||||
# services:
|
||||
#- docker:dind
|
||||
tags:
|
||||
- experimental
|
||||
image: gitlab.manytask.org:5050/go/public-2024-spring
|
||||
script:
|
||||
- testtool grade
|
||||
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
|
||||
rsem/try_lock.lua
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
check:
|
||||
image: cr.yandex/crp9onavos88ug32d5r2/grader/go-build
|
||||
variables:
|
||||
DOCKER_HOST: tcp://docker:2375/
|
||||
DOCKER_TLS_CERTDIR: ""
|
||||
APP_HOST: docker
|
||||
# services:
|
||||
#- docker:dind
|
||||
image: gitlab.manytask.org:5050/go/public-2024-spring/build
|
||||
script:
|
||||
- golangci-lint run --build-tags private,solution ./...
|
||||
#- go test -v -tags private,solution ./...
|
||||
|
@ -19,8 +13,8 @@ rebuild-base-image:
|
|||
- docker
|
||||
when: manual
|
||||
script:
|
||||
- docker build -f build.docker -t cr.yandex/crp9onavos88ug32d5r2/grader/go-build .
|
||||
- docker push cr.yandex/crp9onavos88ug32d5r2/grader/go-build:latest
|
||||
- docker build -f build.docker -t gitlab.manytask.org:5050/go/public-2024-spring/build .
|
||||
- docker push gitlab.manytask.org:5050/go/public-2024-spring/build:latest
|
||||
|
||||
deploy:
|
||||
only:
|
||||
|
@ -28,9 +22,9 @@ deploy:
|
|||
tags:
|
||||
- docker
|
||||
script:
|
||||
- docker pull cr.yandex/crp9onavos88ug32d5r2/grader/go-build:latest
|
||||
- docker build -f testenv.docker -t cr.yandex/crp9onavos88ug32d5r2/grader/go .
|
||||
- docker push cr.yandex/crp9onavos88ug32d5r2/grader/go:latest
|
||||
- docker pull gitlab.manytask.org:5050/go/public-2024-spring/build:latest
|
||||
- docker build -f testenv.docker -t gitlab.manytask.org:5050/go/public-2024-spring .
|
||||
- docker push gitlab.manytask.org:5050/go/public-2024-spring:latest
|
||||
|
||||
build-slides:
|
||||
only:
|
||||
|
@ -38,28 +32,32 @@ build-slides:
|
|||
tags:
|
||||
- docker
|
||||
script:
|
||||
- docker build lectures -t cr.yandex/crp9onavos88ug32d5r2/go-lectures
|
||||
- docker push cr.yandex/crp9onavos88ug32d5r2/go-lectures
|
||||
- docker build lectures -t gitlab.manytask.org:5050/go/public-2024-spring/lectures
|
||||
- docker push gitlab.manytask.org:5050/go/public-2024-spring/lectures
|
||||
|
||||
push-to-public:
|
||||
stage: .post
|
||||
image: cr.yandex/crp9onavos88ug32d5r2/grader/go
|
||||
update-config:
|
||||
only:
|
||||
- master
|
||||
script:
|
||||
- git remote rm public || true
|
||||
- git remote add -f public https://svparamoshkin:${CI_PUSH_TOKEN}@gitlab.manytask.org/go/public-itmo-2023-fall
|
||||
- git config --global user.email 'svparamoshkin@yandex-team.ru'
|
||||
- git config --global user.name 'svparamoshkin'
|
||||
- git fetch public
|
||||
- git branch -D public || true
|
||||
- git branch public public/master
|
||||
- testtool export --push --move-to-master=false
|
||||
- curl -F token=$TESTER_TOKEN http://itmo-go.manytask.org/api/sync_task_columns
|
||||
- >
|
||||
curl -v --fail --silent -X POST \
|
||||
-H "Authorization: Bearer $TESTER_TOKEN" \
|
||||
-H "Content-type: application/x-yaml" \
|
||||
--data-binary "@.manytask.yml" \
|
||||
https://go.manytask.org/api/update_config
|
||||
- >
|
||||
curl -v --fail --silent -X POST \
|
||||
-H "Authorization: Bearer $TESTER_TOKEN" \
|
||||
https://go.manytask.org/api/update_cache
|
||||
|
||||
push-to-github:
|
||||
push-to-public:
|
||||
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:
|
||||
- master
|
||||
script:
|
||||
|
@ -69,7 +67,7 @@ push-to-github:
|
|||
- git branch -D main || true
|
||||
- git checkout -b main
|
||||
- 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
|
||||
|
||||
deploy-slides:
|
||||
|
@ -79,5 +77,5 @@ deploy-slides:
|
|||
tags:
|
||||
- web
|
||||
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
|
||||
|
|
|
@ -1,26 +1,28 @@
|
|||
# Как послать патч
|
||||
|
||||
Если вы нашли недоработку в тестах или неточность/опечатку в условии, то вы можете послать MR
|
||||
Если вы нашли недоработку в тестах или неточность/опечатку в условии, то вы можете послать PR
|
||||
с исправлением в репозиторий курса.
|
||||
|
||||
За все исправления начисляются дополнительные баллы в колонке bugs в таблице.
|
||||
За все исправления начисляются дополнительные баллы в колонке bonus в таблице.
|
||||
Размер дополнительных баллов зависит от серьёзности исправления и определяется преподавателями.
|
||||
|
||||
## Небольшие исправления
|
||||
|
||||
Небольшие исправления на <10 строк проще всего послать через веб интерфейс гитлаба.
|
||||
Небольшие исправления на <10 строк проще всего послать через веб интерфейс гитхаба.
|
||||
|
||||
1. Откройте нужный файл в веб интерфейсе репозитория https://gitlab.com/manytask/itmo-go/private
|
||||
2. Нажмите на кнопку "Edit". Во всплывающей подсказке нажмите кнопку "Fork".
|
||||
![](docs/edit-and-fork.png)
|
||||
3. Внесите изменения в файл. Нажмите "Commit Changes" внизу страницы.
|
||||
4. Добавьте описание вашего изменения. Нажмите "Submit Merge Request".
|
||||
1. Откройте нужный файл в веб интерфейсе репозитория https://github.com/slon/shad-go
|
||||
2. Нажмите на кнопку "Edit in place".
|
||||
![](docs/edit-in-place.png)
|
||||
3. На следующем экране нажмите "Fork this repository".
|
||||
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. Закоммитьте все локальные изменения, которые вы не хотите добавлять в репозиторий курса.
|
||||
|
||||
|
@ -30,16 +32,13 @@
|
|||
git checkout origin/master -b newbranchforupdate
|
||||
```
|
||||
|
||||
4. Внесите локальные изменения и запушьте их в свой форк на [gitlab.com](https://gitlab.com/) (не в `student`), например
|
||||
4. Внесите локальные изменения и запушьте их в свой форк на [github.com](https://github.com/) (не в `student`), например
|
||||
```
|
||||
git add .
|
||||
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 формой нового Merge Request убедитесь, что ветвь назначения — `slon/shad-go:master`. Нажмите кнопку "Create Merge Request".
|
||||
![](docs/create-mr-form.png)
|
||||
На странице c формой нового Pull Request убедитесь, что ветвь назначения — `slon/shad-go:master`. Нажмите кнопку "Create Pull Request".
|
||||
|
|
|
@ -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 с поддержкой модулей.
|
||||
|
||||
## Информация
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
```
|
||||
goos: linux
|
||||
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/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
|
||||
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/main-4 143937 8247 ns/op 4176 B/op 3 allocs/op
|
||||
```
|
||||
|
|
|
@ -5,7 +5,6 @@ package allocs
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
@ -24,7 +23,7 @@ func NewBaselineCounter() Counter {
|
|||
}
|
||||
|
||||
func (c BaselineCounter) Count(r io.Reader) error {
|
||||
data, err := ioutil.ReadAll(r)
|
||||
data, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
|
||||
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 {
|
||||
return nil
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/goleak"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/batcher/slow"
|
||||
"gitlab.com/slon/shad-go/batcher/slow"
|
||||
)
|
||||
|
||||
func TestSimple(t *testing.T) {
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/blowfish"
|
||||
"gitlab.com/slon/shad-go/blowfish"
|
||||
)
|
||||
|
||||
var _ cipher.Block = (*blowfish.Blowfish)(nil)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.20
|
||||
FROM golang:1.22
|
||||
|
||||
# enable backports for git-filter-repo
|
||||
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 \
|
||||
&& 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'а
|
||||
testtool: copying go.mod, go.sum and .golangci.yml
|
||||
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)
|
||||
sum_test.go:19: 2 + 2 == 0 != 4
|
||||
sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/tools/testtool"
|
||||
"gitlab.com/slon/shad-go/tools/testtool"
|
||||
)
|
||||
|
||||
type testCase struct {
|
||||
|
@ -93,7 +93,7 @@ testtool: copying !change files
|
|||
testtool: copying testdata directory
|
||||
testtool: copying go.mod, go.sum and .golangci.yml
|
||||
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)
|
||||
sum_test.go:19: 2 + 2 == 0 != 4
|
||||
sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808
|
||||
|
@ -113,7 +113,7 @@ ERROR: Job failed: exit code 1`,
|
|||
Stage: test, Job grade
|
||||
testtool: copying go.mod, go.sum and .golangci.yml
|
||||
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)
|
||||
sum_test.go:19: 2 + 2 == 0 != 4
|
||||
sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808
|
||||
|
@ -156,7 +156,7 @@ testtool: copying !change files
|
|||
testtool: copying testdata directory
|
||||
testtool: copying go.mod, go.sum and .golangci.yml
|
||||
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)
|
||||
sum_test.go:19: 2 + 2 == 0 != 4
|
||||
sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808
|
||||
|
@ -188,7 +188,7 @@ ERROR: Job failed: exit code 1`,
|
|||
Stage: %v, Job %v
|
||||
testtool: copying go.mod, go.sum and .golangci.yml
|
||||
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)
|
||||
sum_test.go:19: 2 + 2 == 0 != 4
|
||||
sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cond
|
||||
|
||||
import (
|
||||
"gitlab.com/slon/shad-go/tools/testtool"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -44,6 +45,38 @@ func TestCondSignal(t *testing.T) {
|
|||
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) {
|
||||
var m sync.Mutex
|
||||
c := New(&m)
|
||||
|
@ -182,3 +215,7 @@ func TestCondSignalStealing(t *testing.T) {
|
|||
cond.Broadcast()
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoSyncPackageImported(t *testing.T) {
|
||||
testtool.CheckForbiddenImport(t, "sync")
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ func TestHash_EvenDistribution(t *testing.T) {
|
|||
h.AddNode(&n)
|
||||
}
|
||||
|
||||
counts := map[*node]int{}
|
||||
counts := map[*node]float64{}
|
||||
const N = 1 << 16
|
||||
for i := 0; i < N; i++ {
|
||||
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 variance = N * (P) * (1 - P)
|
||||
stddev := math.Sqrt(variance)
|
||||
t.Logf("P = %v, var = %v, stddev = %v", P, variance, stddev)
|
||||
idealStddev := math.Sqrt(variance)
|
||||
|
||||
t.Logf("P = %v, var = %v, stddev = %v", P, variance, idealStddev)
|
||||
t.Logf("counts = %v", maps.Values(counts))
|
||||
|
||||
total := float64(N)
|
||||
mean := total / K
|
||||
|
||||
var dispersion float64
|
||||
for _, count := range counts {
|
||||
require.Greater(t, count, int(N/K-stddev*10))
|
||||
require.Less(t, count, int(N/K+stddev*10))
|
||||
dispersion += (count - mean) * (count - mean)
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -12,8 +12,8 @@ import (
|
|||
"github.com/gorilla/handlers"
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/coverme/models"
|
||||
"gitlab.com/manytask/itmo-go/private/coverme/utils"
|
||||
"gitlab.com/slon/shad-go/coverme/models"
|
||||
"gitlab.com/slon/shad-go/coverme/utils"
|
||||
)
|
||||
|
||||
type App struct {
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/coverme/models"
|
||||
"gitlab.com/slon/shad-go/coverme/models"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
|
|
|
@ -5,8 +5,8 @@ package main
|
|||
import (
|
||||
"flag"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/coverme/app"
|
||||
"gitlab.com/manytask/itmo-go/private/coverme/models"
|
||||
"gitlab.com/slon/shad-go/coverme/app"
|
||||
"gitlab.com/slon/shad-go/coverme/models"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
|
|
@ -31,18 +31,14 @@ sudo apt install postgresql
|
|||
Альтернативный способ — запустить бд в докере.
|
||||
|
||||
Для этого нужно установить 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 через переменную окружения, удаляет контейнеры в конце.
|
||||
|
||||
Как подчистить контейнеры, если что-то пошло не так:
|
||||
```
|
||||
(cd dao && docker-compose down)
|
||||
(cd dao && docker compose down)
|
||||
```
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/goleak"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/pgfixture"
|
||||
"gitlab.com/slon/shad-go/pgfixture"
|
||||
)
|
||||
|
||||
func TestDao(t *testing.T) {
|
||||
|
@ -36,7 +36,7 @@ func TestDao(t *testing.T) {
|
|||
|
||||
alice, err := dao.Lookup(ctx, aliceID)
|
||||
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))
|
||||
|
||||
|
@ -44,6 +44,7 @@ func TestDao(t *testing.T) {
|
|||
require.ErrorIs(t, err, sql.ErrNoRows)
|
||||
|
||||
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)
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -8,3 +8,8 @@ services:
|
|||
POSTGRES_PASSWORD: pass
|
||||
ports:
|
||||
- 5432:5432
|
||||
healthcheck:
|
||||
test: [ "CMD-SHELL", "pg_isready -U $${POSTGRES_USER}" ]
|
||||
interval: 1s
|
||||
timeout: 3s
|
||||
retries: 5
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"fmt"
|
||||
"image"
|
||||
"image/png"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
|
@ -18,10 +17,10 @@ import (
|
|||
|
||||
"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
|
||||
|
||||
|
@ -125,7 +124,7 @@ func TestDigitalClock_valid(t *testing.T) {
|
|||
port, stop := startServer(t)
|
||||
defer stop()
|
||||
|
||||
files, err := ioutil.ReadDir("./testdata")
|
||||
files, err := os.ReadDir("./testdata")
|
||||
require.NoError(t, err)
|
||||
|
||||
c := &http.Client{Timeout: time.Second * 10}
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
@ -17,13 +16,13 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/goleak"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/api"
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/artifact"
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/client"
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/dist"
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/filecache"
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/worker"
|
||||
"gitlab.com/manytask/itmo-go/private/tools/testtool"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/api"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/artifact"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/client"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/dist"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/filecache"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/worker"
|
||||
"gitlab.com/slon/shad-go/tools/testtool"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
@ -50,7 +49,11 @@ type Config struct {
|
|||
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()
|
||||
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())
|
||||
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) {
|
||||
rootDir, err = ioutil.TempDir("", "")
|
||||
rootDir, err = os.MkdirTemp("", "")
|
||||
require.NoError(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
|
@ -90,6 +93,10 @@ func newEnv(t *testing.T, config *Config) (e *env, cancel func()) {
|
|||
env.Logger, err = cfg.Build()
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(func() {
|
||||
_ = env.Logger.Sync()
|
||||
})
|
||||
|
||||
t.Helper()
|
||||
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()
|
||||
env.Ctx, cancelRootContext = context.WithCancel(context.Background())
|
||||
t.Cleanup(cancelRootContext)
|
||||
|
||||
env.Client = client.NewClient(
|
||||
env.Logger.Named("client"),
|
||||
|
@ -113,6 +121,7 @@ func newEnv(t *testing.T, config *Config) (e *env, cancel func()) {
|
|||
env.Logger.Named("coordinator"),
|
||||
coordinatorCache,
|
||||
)
|
||||
t.Cleanup(env.Coordinator.Stop)
|
||||
|
||||
router := http.NewServeMux()
|
||||
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 {
|
||||
go func(w *worker.Worker) {
|
||||
err := w.Run(env.Ctx)
|
||||
|
@ -181,20 +195,14 @@ func newEnv(t *testing.T, config *Config) (e *env, cancel func()) {
|
|||
}
|
||||
}()
|
||||
|
||||
return env, func() {
|
||||
cancelRootContext()
|
||||
_ = env.HTTP.Shutdown(context.Background())
|
||||
_ = env.Logger.Sync()
|
||||
|
||||
goleak.VerifyNone(t)
|
||||
}
|
||||
return env
|
||||
}
|
||||
|
||||
func newWinFileSink(u *url.URL) (zap.Sink, error) {
|
||||
if len(u.Opaque) > 0 {
|
||||
// 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
|
||||
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
|
||||
|
||||
import (
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||
)
|
||||
|
||||
type JobResult struct {
|
||||
|
|
|
@ -2,13 +2,14 @@ package disttest
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"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}
|
||||
|
@ -26,8 +27,7 @@ var echoGraph = build.Graph{
|
|||
}
|
||||
|
||||
func TestSingleCommand(t *testing.T) {
|
||||
env, cancel := newEnv(t, singleWorkerConfig)
|
||||
defer cancel()
|
||||
env := newEnv(t, singleWorkerConfig)
|
||||
|
||||
recorder := NewRecorder()
|
||||
require.NoError(t, env.Client.Build(env.Ctx, echoGraph, recorder))
|
||||
|
@ -37,10 +37,9 @@ func TestSingleCommand(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestJobCaching(t *testing.T) {
|
||||
env, cancel := newEnv(t, singleWorkerConfig)
|
||||
defer cancel()
|
||||
env := newEnv(t, singleWorkerConfig)
|
||||
|
||||
tmpFile, err := ioutil.TempFile("", "")
|
||||
tmpFile, err := os.CreateTemp("", "")
|
||||
require.NoError(t, err)
|
||||
|
||||
graph := build.Graph{
|
||||
|
@ -62,12 +61,12 @@ func TestJobCaching(t *testing.T) {
|
|||
assert.Len(t, recorder.Jobs, 1)
|
||||
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.
|
||||
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.Equal(t, []byte("NOTOK\n"), output)
|
||||
}
|
||||
|
@ -94,8 +93,7 @@ var sourceFilesGraph = build.Graph{
|
|||
}
|
||||
|
||||
func TestSourceFiles(t *testing.T) {
|
||||
env, cancel := newEnv(t, singleWorkerConfig)
|
||||
defer cancel()
|
||||
env := newEnv(t, singleWorkerConfig)
|
||||
|
||||
recorder := NewRecorder()
|
||||
require.NoError(t, env.Client.Build(env.Ctx, sourceFilesGraph, recorder))
|
||||
|
@ -125,8 +123,7 @@ var artifactTransferGraph = build.Graph{
|
|||
}
|
||||
|
||||
func TestArtifactTransferBetweenJobs(t *testing.T) {
|
||||
env, cancel := newEnv(t, singleWorkerConfig)
|
||||
defer cancel()
|
||||
env := newEnv(t, singleWorkerConfig)
|
||||
|
||||
recorder := NewRecorder()
|
||||
require.NoError(t, env.Client.Build(env.Ctx, artifactTransferGraph, recorder))
|
||||
|
|
|
@ -9,14 +9,13 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
"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}
|
||||
|
||||
func TestArtifactTransferBetweenWorkers(t *testing.T) {
|
||||
env, cancel := newEnv(t, threeWorkerConfig)
|
||||
defer cancel()
|
||||
env := newEnv(t, threeWorkerConfig)
|
||||
|
||||
baseJob := build.Job{
|
||||
ID: build.ID{'a'},
|
||||
|
|
|
@ -3,7 +3,7 @@ package api
|
|||
import (
|
||||
"context"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||
)
|
||||
|
||||
type BuildRequest struct {
|
||||
|
@ -25,7 +25,8 @@ type BuildFailed struct {
|
|||
Error string
|
||||
}
|
||||
|
||||
type BuildFinished struct{}
|
||||
type BuildFinished struct {
|
||||
}
|
||||
|
||||
type UploadDone struct{}
|
||||
|
||||
|
@ -33,7 +34,8 @@ type SignalRequest struct {
|
|||
UploadDone *UploadDone
|
||||
}
|
||||
|
||||
type SignalResponse struct{}
|
||||
type SignalResponse struct {
|
||||
}
|
||||
|
||||
type StatusWriter interface {
|
||||
Started(rsp *BuildStarted) error
|
||||
|
|
|
@ -7,10 +7,11 @@ import (
|
|||
|
||||
"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 {
|
||||
panic("implement me")
|
||||
|
|
|
@ -12,9 +12,9 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap/zaptest"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/api"
|
||||
mock "gitlab.com/manytask/itmo-go/private/distbuild/pkg/api/mock"
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/api"
|
||||
mock "gitlab.com/slon/shad-go/distbuild/pkg/api/mock"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||
)
|
||||
|
||||
//go:generate mockgen -package mock -destination mock/mock.go . Service
|
||||
|
@ -28,7 +28,6 @@ type env struct {
|
|||
|
||||
func (e *env) stop() {
|
||||
e.server.Close()
|
||||
e.ctrl.Finish()
|
||||
}
|
||||
|
||||
func newEnv(t *testing.T) (*env, func()) {
|
||||
|
@ -56,8 +55,8 @@ func TestBuildSignal(t *testing.T) {
|
|||
|
||||
ctx := context.Background()
|
||||
|
||||
buildIDa := build.ID{0o1}
|
||||
buildIDb := build.ID{0o2}
|
||||
buildIDa := build.ID{01}
|
||||
buildIDb := build.ID{02}
|
||||
req := &api.SignalRequest{}
|
||||
rsp := &api.SignalResponse{}
|
||||
|
||||
|
@ -91,10 +90,10 @@ func TestBuildRunning(t *testing.T) {
|
|||
|
||||
ctx := context.Background()
|
||||
|
||||
buildID := build.ID{0o2}
|
||||
buildID := build.ID{02}
|
||||
|
||||
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}
|
||||
|
@ -141,7 +140,7 @@ func TestBuildResultsStreaming(t *testing.T) {
|
|||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
buildID := build.ID{0o2}
|
||||
buildID := build.ID{02}
|
||||
req := &api.BuildRequest{}
|
||||
started := &api.BuildStarted{ID: buildID}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ package api
|
|||
import (
|
||||
"context"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||
)
|
||||
|
||||
// JobResult описывает результат работы джоба.
|
||||
|
|
|
@ -11,16 +11,15 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap/zaptest"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/api"
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/api/mock"
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/api"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/api/mock"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||
)
|
||||
|
||||
//go:generate mockgen -package mock -destination mock/heartbeat.go . HeartbeatService
|
||||
|
||||
func TestHeartbeat(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
l := zaptest.NewLogger(t)
|
||||
m := mock.NewMockHeartbeatService(ctrl)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// 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
|
||||
|
@ -7,7 +7,7 @@ package mock
|
|||
import (
|
||||
context "context"
|
||||
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"
|
||||
)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// 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
|
||||
|
@ -7,8 +7,8 @@ package mock
|
|||
import (
|
||||
context "context"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
api "gitlab.com/manytask/itmo-go/private/distbuild/pkg/api"
|
||||
build "gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
||||
api "gitlab.com/slon/shad-go/distbuild/pkg/api"
|
||||
build "gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
|
|
|
@ -4,12 +4,11 @@ import (
|
|||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -34,18 +33,18 @@ func NewCache(root string) (*Cache, error) {
|
|||
if err := os.RemoveAll(tmpDir); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := os.MkdirAll(tmpDir, 0o777); err != nil {
|
||||
if err := os.MkdirAll(tmpDir, 0777); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cacheDir := filepath.Join(root, "c")
|
||||
if err := os.MkdirAll(cacheDir, 0o777); err != nil {
|
||||
if err := os.MkdirAll(cacheDir, 0777); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := 0; i < 256; 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
|
||||
}
|
||||
}
|
||||
|
@ -110,13 +109,13 @@ func (c *Cache) writeUnlock(id build.ID) {
|
|||
}
|
||||
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
||||
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 {
|
||||
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())
|
||||
if err = os.MkdirAll(path, 0o777); err != nil {
|
||||
if err = os.MkdirAll(path, 0777); err != nil {
|
||||
c.writeUnlock(artifact)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -2,15 +2,14 @@ package artifact_test
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/artifact"
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/artifact"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||
)
|
||||
|
||||
type testCache struct {
|
||||
|
@ -23,7 +22,7 @@ func (c *testCache) cleanup() {
|
|||
}
|
||||
|
||||
func newTestCache(t *testing.T) *testCache {
|
||||
tmpDir, err := ioutil.TempDir("", "")
|
||||
tmpDir, err := os.MkdirTemp("", "")
|
||||
require.NoError(t, err)
|
||||
|
||||
cache, err := artifact.NewCache(tmpDir)
|
||||
|
|
|
@ -5,7 +5,7 @@ package artifact
|
|||
import (
|
||||
"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.
|
||||
|
|
|
@ -2,17 +2,17 @@ package artifact_test
|
|||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap/zaptest"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/artifact"
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/artifact"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||
)
|
||||
|
||||
func TestArtifactTransfer(t *testing.T) {
|
||||
|
@ -23,7 +23,7 @@ func TestArtifactTransfer(t *testing.T) {
|
|||
|
||||
dir, commit, _, err := remoteCache.Create(id)
|
||||
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())
|
||||
|
||||
l := zaptest.NewLogger(t)
|
||||
|
@ -42,7 +42,7 @@ func TestArtifactTransfer(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
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.Equal(t, []byte("foobar"), content)
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ type Job struct {
|
|||
// exec - выполняет произвольную команду
|
||||
// cat - записывает строку в файл
|
||||
//
|
||||
// Все строки в описании команды могут содержать в себе на переменные. Перед выполнением
|
||||
// Все строки в описании команды могут содержать в себе ссылки на контекстные переменные. Перед выполнением
|
||||
// реальной команды, переменные заменяются на их реальные значения.
|
||||
//
|
||||
// {{.OutputDir}} - абсолютный путь до выходной директории джоба.
|
||||
|
|
|
@ -7,10 +7,11 @@ import (
|
|||
|
||||
"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,
|
||||
|
|
9
distbuild/pkg/dist/coordinator.go
vendored
9
distbuild/pkg/dist/coordinator.go
vendored
|
@ -8,11 +8,12 @@ import (
|
|||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/filecache"
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/scheduler"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/filecache"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/scheduler"
|
||||
)
|
||||
|
||||
type Coordinator struct{}
|
||||
type Coordinator struct {
|
||||
}
|
||||
|
||||
var defaultConfig = scheduler.Config{
|
||||
CacheTimeout: time.Millisecond * 10,
|
||||
|
@ -26,6 +27,8 @@ func NewCoordinator(
|
|||
panic("implement me")
|
||||
}
|
||||
|
||||
func (c *Coordinator) Stop() {}
|
||||
|
||||
func (c *Coordinator) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
|
|
@ -7,10 +7,11 @@ import (
|
|||
|
||||
"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 {
|
||||
panic("implement me")
|
||||
|
|
|
@ -3,9 +3,9 @@ package filecache_test
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
|
@ -14,8 +14,8 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap/zaptest"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/filecache"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/filecache"
|
||||
)
|
||||
|
||||
type env struct {
|
||||
|
@ -52,7 +52,7 @@ func TestFileUpload(t *testing.T) {
|
|||
content := bytes.Repeat([]byte("foobar"), 1024*1024)
|
||||
|
||||
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()
|
||||
|
||||
|
@ -65,7 +65,7 @@ func TestFileUpload(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
defer unlock()
|
||||
|
||||
actualContent, err := ioutil.ReadFile(path)
|
||||
actualContent, err := os.ReadFile(path)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, content, actualContent)
|
||||
})
|
||||
|
@ -123,7 +123,7 @@ func TestFileDownload(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
defer unlock()
|
||||
|
||||
content, err := ioutil.ReadFile(path)
|
||||
content, err := os.ReadFile(path)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []byte("foobar"), content)
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/artifact"
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/artifact"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
@ -2,14 +2,13 @@ package filecache_test
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/filecache"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/filecache"
|
||||
)
|
||||
|
||||
type testCache struct {
|
||||
|
@ -18,7 +17,7 @@ type testCache struct {
|
|||
}
|
||||
|
||||
func newCache(t *testing.T) *testCache {
|
||||
tmpDir, err := ioutil.TempDir("", "filecache")
|
||||
tmpDir, err := os.MkdirTemp("", "filecache")
|
||||
require.NoError(t, err)
|
||||
|
||||
c, err := filecache.New(tmpDir)
|
||||
|
@ -36,25 +35,25 @@ func (c *testCache) cleanup() {
|
|||
func TestFileCache(t *testing.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, abort())
|
||||
|
||||
_, _, err = cache.Get(build.ID{0o1})
|
||||
_, _, err = cache.Get(build.ID{01})
|
||||
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)
|
||||
|
||||
_, err = f.Write([]byte("foo bar"))
|
||||
require.NoError(t, err)
|
||||
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)
|
||||
defer unlock()
|
||||
|
||||
content, err := ioutil.ReadFile(path)
|
||||
content, err := os.ReadFile(path)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []byte("foo bar"), content)
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@ import (
|
|||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/api"
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/build"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/api"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
||||
)
|
||||
|
||||
var TimeAfter = time.After
|
||||
|
@ -25,7 +25,8 @@ type Config struct {
|
|||
DepsTimeout time.Duration
|
||||
}
|
||||
|
||||
type Scheduler struct{}
|
||||
type Scheduler struct {
|
||||
}
|
||||
|
||||
func NewScheduler(l *zap.Logger, config Config) *Scheduler {
|
||||
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 {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (c *Scheduler) Stop() {
|
||||
panic("implement me")
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package tarstream_test
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
@ -10,11 +9,11 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
"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) {
|
||||
tmpDir, err := ioutil.TempDir("", "tarstream")
|
||||
tmpDir, err := os.MkdirTemp("", "tarstream")
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Logf("running inside %s", tmpDir)
|
||||
|
@ -22,15 +21,15 @@ func TestTarStream(t *testing.T) {
|
|||
from := filepath.Join(tmpDir, "from")
|
||||
to := filepath.Join(tmpDir, "to")
|
||||
|
||||
require.NoError(t, os.Mkdir(from, 0o777))
|
||||
require.NoError(t, os.Mkdir(to, 0o777))
|
||||
require.NoError(t, os.Mkdir(from, 0777))
|
||||
require.NoError(t, os.Mkdir(to, 0777))
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
||||
require.NoError(t, os.Mkdir(filepath.Join(from, "a"), 0o777))
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(from, "b", "c", "d"), 0o777))
|
||||
require.NoError(t, ioutil.WriteFile(filepath.Join(from, "a", "x.bin"), []byte("xxx"), 0o777))
|
||||
require.NoError(t, ioutil.WriteFile(filepath.Join(from, "b", "c", "y.txt"), []byte("yyy"), 0o666))
|
||||
require.NoError(t, os.Mkdir(filepath.Join(from, "a"), 0777))
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(from, "b", "c", "d"), 0777))
|
||||
require.NoError(t, os.WriteFile(filepath.Join(from, "a", "x.bin"), []byte("xxx"), 0777))
|
||||
require.NoError(t, os.WriteFile(filepath.Join(from, "b", "c", "y.txt"), []byte("yyy"), 0666))
|
||||
|
||||
require.NoError(t, tarstream.Send(from, &buf))
|
||||
|
||||
|
@ -53,15 +52,15 @@ func TestTarStream(t *testing.T) {
|
|||
|
||||
require.Equal(t, mode.String(), st.Mode().String())
|
||||
|
||||
b, err := ioutil.ReadFile(path)
|
||||
b, err := os.ReadFile(path)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, content, b)
|
||||
}
|
||||
|
||||
checkFile(filepath.Join(to, "a", "x.bin"), []byte("xxx"), 0o755)
|
||||
checkFile(filepath.Join(to, "b", "c", "y.txt"), []byte("yyy"), 0o644)
|
||||
checkFile(filepath.Join(to, "a", "x.bin"), []byte("xxx"), 0755)
|
||||
checkFile(filepath.Join(to, "b", "c", "y.txt"), []byte("yyy"), 0644)
|
||||
}
|
||||
|
||||
func init() {
|
||||
unix.Umask(0o022)
|
||||
unix.Umask(0022)
|
||||
}
|
||||
|
|
|
@ -8,12 +8,13 @@ import (
|
|||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/api"
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/artifact"
|
||||
"gitlab.com/manytask/itmo-go/private/distbuild/pkg/filecache"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/api"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/artifact"
|
||||
"gitlab.com/slon/shad-go/distbuild/pkg/filecache"
|
||||
)
|
||||
|
||||
type Worker struct{}
|
||||
type Worker struct {
|
||||
}
|
||||
|
||||
func New(
|
||||
workerID api.WorkerID,
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
✗ go test -v -run=^$ -bench=BenchmarkSprintf -memprofile=mem.out ./varfmt/...
|
||||
goos: linux
|
||||
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
|
||||
BenchmarkSprintf
|
||||
BenchmarkSprintf/small
|
||||
|
@ -17,7 +17,7 @@ BenchmarkSprintf/small_string-8 13282659 84.48 ns/op 16 B/op
|
|||
BenchmarkSprintf/big
|
||||
BenchmarkSprintf/big-8 20089 62372 ns/op 16388 B/op 1 allocs/op
|
||||
PASS
|
||||
ok gitlab.com/manytask/itmo-go/private/varfmt 4.363s
|
||||
ok gitlab.com/slon/shad-go/varfmt 4.363s
|
||||
```
|
||||
|
||||
Сэмплы профайлера будут записаны в бинарный файл `mem.out`.
|
||||
|
@ -53,7 +53,7 @@ Showing nodes accounting for 715.73MB, 99.37% of 720.23MB total
|
|||
Dropped 24 nodes (cum <= 3.60MB)
|
||||
flat flat% sum% cum cum%
|
||||
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).runN
|
||||
(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"
|
||||
"log"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/gitfame/configs"
|
||||
"gitlab.com/manytask/itmo-go/private/gitfame/internal"
|
||||
"gitlab.com/slon/shad-go/gitfame/configs"
|
||||
"gitlab.com/slon/shad-go/gitfame/internal"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
|
@ -81,8 +81,8 @@ import (
|
|||
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/gitfame/configs"
|
||||
"gitlab.com/manytask/itmo-go/private/gitfame/internal"
|
||||
"gitlab.com/slon/shad-go/gitfame/configs"
|
||||
"gitlab.com/slon/shad-go/gitfame/internal"
|
||||
)
|
||||
```
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
Low-level programming. unsafe. Package binary. bytes.Buffer. cgo, syscall.
|
||||
|
||||
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.
|
||||
Build tags. go modules. godoc. Code generation.
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gitlab.com/slon/shad-go/tools/testtool"
|
||||
"go.uber.org/goleak"
|
||||
)
|
||||
|
||||
|
@ -38,6 +39,23 @@ func TestCall_Simple(t *testing.T) {
|
|||
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) {
|
||||
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"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
@ -12,7 +11,7 @@ import (
|
|||
|
||||
"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) {
|
||||
|
@ -33,6 +32,32 @@ func TestMerge(t *testing.T) {
|
|||
1
|
||||
1
|
||||
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")
|
||||
|
||||
readTestCase := func(dir string) (in []string, out string) {
|
||||
files, err := ioutil.ReadDir(dir)
|
||||
files, err := os.ReadDir(dir)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, f := range files {
|
||||
|
@ -84,7 +109,7 @@ func TestSort(t *testing.T) {
|
|||
testCaseDir := path.Join(testDir, d)
|
||||
|
||||
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)
|
||||
defer func() { _ = os.RemoveAll(tmpDir) }()
|
||||
|
||||
|
@ -95,7 +120,7 @@ func TestSort(t *testing.T) {
|
|||
w := bufio.NewWriter(&buf)
|
||||
require.NoError(t, Sort(w, in...))
|
||||
|
||||
expected, err := ioutil.ReadFile(out)
|
||||
expected, err := os.ReadFile(out)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, w.Flush())
|
||||
|
@ -107,7 +132,7 @@ func TestSort(t *testing.T) {
|
|||
func listDirs(t *testing.T, dir string) []string {
|
||||
t.Helper()
|
||||
|
||||
files, err := ioutil.ReadDir(dir)
|
||||
files, err := os.ReadDir(dir)
|
||||
require.NoError(t, err)
|
||||
|
||||
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 {
|
||||
t.Helper()
|
||||
|
||||
data, err := ioutil.ReadFile(f)
|
||||
data, err := os.ReadFile(f)
|
||||
require.NoError(t, err)
|
||||
|
||||
dst := path.Join(dir, path.Base(f))
|
||||
err = ioutil.WriteFile(dst, data, 0o644)
|
||||
err = os.WriteFile(dst, data, 0644)
|
||||
require.NoError(t, err)
|
||||
|
||||
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
|
||||
|
||||
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"
|
||||
|
||||
"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
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package fileleak_test
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
|
@ -11,8 +10,8 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/fileleak"
|
||||
"gitlab.com/manytask/itmo-go/private/tools/testtool"
|
||||
"gitlab.com/slon/shad-go/fileleak"
|
||||
"gitlab.com/slon/shad-go/tools/testtool"
|
||||
)
|
||||
|
||||
type fakeT struct {
|
||||
|
@ -75,7 +74,7 @@ func TestFileLeak_ReopenFile(t *testing.T) {
|
|||
checkLeak(t, true, func() {
|
||||
_ = f.Close()
|
||||
|
||||
ff, err := ioutil.TempFile("", "")
|
||||
ff, err := os.CreateTemp("", "")
|
||||
require.NoError(t, err)
|
||||
f = ff
|
||||
})
|
||||
|
@ -129,6 +128,7 @@ func TestFileLeak_DupLeak(t *testing.T) {
|
|||
var err error
|
||||
fd, err = syscall.Dup(1)
|
||||
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
|
||||
|
||||
* 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
|
||||
* regexp: https://golang.org/pkg/regexp/
|
||||
|
|
|
@ -3,7 +3,6 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
|
@ -15,10 +14,10 @@ import (
|
|||
"github.com/go-resty/resty/v2"
|
||||
"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
|
||||
|
||||
|
@ -36,7 +35,7 @@ func storeConfig(t *testing.T, conf string) (filename string, cleanup func()) {
|
|||
t.Helper()
|
||||
|
||||
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)
|
||||
|
||||
cleanup = func() { _ = os.Remove(filename) }
|
||||
|
|
|
@ -79,6 +79,18 @@ Stack:
|
|||
а `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
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
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.
|
||||
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.
|
||||
//
|
||||
// Returns resulting stack state and an 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 /"},
|
||||
expected: []int{2},
|
||||
},
|
||||
{
|
||||
description: "add non-empty stack",
|
||||
input: []string{"1 2 3 +"},
|
||||
expected: []int{1, 5},
|
||||
},
|
||||
{
|
||||
description: "dup",
|
||||
input: []string{"1 dup"},
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/goleak"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/genericsum"
|
||||
"gitlab.com/slon/shad-go/genericsum"
|
||||
)
|
||||
|
||||
func TestMin(t *testing.T) {
|
||||
|
@ -184,11 +184,42 @@ func TestIsHermitianMatrix(t *testing.T) {
|
|||
{7, 2, 12},
|
||||
{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{
|
||||
{1, 12, 8},
|
||||
{3, 4, 7},
|
||||
{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{
|
||||
{1, 3 + 2i},
|
||||
{3 - 2i, 4},
|
||||
|
|
|
@ -175,6 +175,11 @@ export PATH=$GOPATH/bin:$PATH
|
|||
|
||||
После этого `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
|
||||
|
||||
Прочитайте и исправьте [распространённые ошибки](../docs/gitfame_review_comments.md).
|
||||
|
|
|
@ -2,7 +2,6 @@ package integration
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
|
@ -14,10 +13,10 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
"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
|
||||
|
||||
|
@ -43,7 +42,7 @@ func TestGitFame(t *testing.T) {
|
|||
tc := ReadTestCase(t, filepath.Join(testsDir, dir))
|
||||
|
||||
t.Run(dir+"/"+tc.Name, func(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "gitfame-")
|
||||
dir, err := os.MkdirTemp("", "gitfame-")
|
||||
require.NoError(t, err)
|
||||
defer func() { _ = os.RemoveAll(dir) }()
|
||||
|
||||
|
@ -75,7 +74,7 @@ func TestGitFame(t *testing.T) {
|
|||
func ListTestDirs(t *testing.T, path string) []string {
|
||||
t.Helper()
|
||||
|
||||
files, err := ioutil.ReadDir(path)
|
||||
files, err := os.ReadDir(path)
|
||||
require.NoError(t, err)
|
||||
|
||||
var names []string
|
||||
|
@ -109,7 +108,7 @@ func ReadTestCase(t *testing.T, path string) *TestCase {
|
|||
|
||||
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)
|
||||
|
||||
return &TestCase{TestDescription: desc, Expected: expected}
|
||||
|
@ -126,7 +125,7 @@ type TestDescription struct {
|
|||
func ReadTestDescription(t *testing.T, path string) *TestDescription {
|
||||
t.Helper()
|
||||
|
||||
data, err := ioutil.ReadFile(filepath.Join(path, "description.yaml"))
|
||||
data, err := os.ReadFile(filepath.Join(path, "description.yaml"))
|
||||
require.NoError(t, err)
|
||||
|
||||
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 (
|
||||
github.com/felixge/httpsnoop v1.0.3
|
||||
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-resty/resty/v2 v2.1.0
|
||||
github.com/gofrs/uuid v3.3.0+incompatible
|
||||
github.com/golang/mock v1.4.1
|
||||
github.com/google/go-cmp v0.5.9
|
||||
github.com/golang/mock v1.6.0
|
||||
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/mux v1.7.4
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/jackc/pgx/v4 v4.6.0
|
||||
github.com/jonboulle/clockwork v0.1.0
|
||||
github.com/jackc/pgx/v5 v5.5.3
|
||||
github.com/jonboulle/clockwork v0.4.0
|
||||
github.com/spf13/cobra v1.1.3
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.8.2
|
||||
go.uber.org/goleak v1.0.0
|
||||
go.uber.org/zap v1.14.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
go.uber.org/goleak v1.3.0
|
||||
go.uber.org/zap v1.26.0
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29
|
||||
golang.org/x/perf v0.0.0-20191209155426-36b577b0eb03
|
||||
golang.org/x/sync v0.1.0
|
||||
golang.org/x/sys v0.7.0
|
||||
golang.org/x/tools v0.7.0
|
||||
golang.org/x/sync v0.6.0
|
||||
golang.org/x/sys v0.17.0
|
||||
golang.org/x/tools v0.18.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
|
||||
)
|
||||
|
||||
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/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/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/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/pgproto3/v2 v2.0.1 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8 // indirect
|
||||
github.com/jackc/pgtype v1.3.0 // indirect
|
||||
github.com/kr/pretty v0.3.0 // indirect
|
||||
github.com/lib/pq v1.10.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.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
|
||||
go.uber.org/atomic v1.5.0 // indirect
|
||||
go.uber.org/multierr v1.3.0 // indirect
|
||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee // indirect
|
||||
golang.org/x/crypto v0.5.0 // indirect
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de // indirect
|
||||
golang.org/x/mod v0.9.0 // indirect
|
||||
golang.org/x/net v0.9.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 // indirect
|
||||
github.com/xuri/excelize/v2 v2.8.1 // indirect
|
||||
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 // indirect
|
||||
go.uber.org/multierr v1.10.0 // indirect
|
||||
golang.org/x/crypto v0.19.0 // indirect
|
||||
golang.org/x/mod v0.15.0 // indirect
|
||||
golang.org/x/net v0.21.0 // indirect
|
||||
golang.org/x/text v0.14.0 // 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
|
||||
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/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
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=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
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/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/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-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/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/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-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 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/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/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
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/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
|
||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
|
||||
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/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-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/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/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||
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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
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/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
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/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
||||
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.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/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/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-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
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-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/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/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
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/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-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.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.4.1 h1:ocYkMQY5RrXTYgXl7ICpV0IXwlEQGwKIsery4gyXa1U=
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
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.3.1/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/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.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.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.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
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/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=
|
||||
|
@ -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/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
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/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.1 h1:Rdjp4NFjwHnEslx2b66FfCI2S0LhO4itac3hXz6WX9M=
|
||||
github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8 h1:Q3tB+ExeflWUW7AFcAhXqk40s9mnNYLk1nOkKNZ5GnU=
|
||||
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/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.5.3 h1:Ces6/M3wbDXYpM8JyyPD57ivTtJACFZJd885pdIaV2s=
|
||||
github.com/jackc/pgx/v5 v5.5.3/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
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/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/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/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.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/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.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
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.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
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/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.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/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
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/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/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/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/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/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.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
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/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 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-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.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-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/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/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.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||
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/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
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/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/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 h1:pntxY8Ary0t43dCZ5dqY4YTJCObLY1kIXl0uzMv+7DE=
|
||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
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/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.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
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/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
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/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.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
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/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
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.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.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.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
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/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/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.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
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.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
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/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
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.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||
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/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
|
||||
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
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.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
||||
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-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-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-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-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
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-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
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-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-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
|
||||
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-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.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
|
||||
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
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-20180826012351-8a410e7b638d/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-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-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
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-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
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-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.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.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-20180830151530-49385e6e1522/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-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-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-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-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-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-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-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
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.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.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
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-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
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-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-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-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-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-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-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.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
|
||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
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-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-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
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.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.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.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/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-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/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
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/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/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.2.1/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-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.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
||||
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/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 (
|
||||
"time"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/gossip/meshpb"
|
||||
"gitlab.com/slon/shad-go/gossip/meshpb"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"gitlab.com/manytask/itmo-go/private/gossip"
|
||||
"gitlab.com/manytask/itmo-go/private/gossip/meshpb"
|
||||
"gitlab.com/slon/shad-go/gossip"
|
||||
"gitlab.com/slon/shad-go/gossip/meshpb"
|
||||
"go.uber.org/goleak"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
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.
|
||||
message PeerMeta {
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
```
|
||||
goos: linux
|
||||
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
|
||||
BenchmarkEncodeSimple
|
||||
BenchmarkEncodeSimple-8 7047 176628 ns/op 813872 B/op 17 allocs/op
|
||||
BenchmarkEncode
|
||||
BenchmarkEncode-8 41706 32616 ns/op 19 B/op 0 allocs/op
|
||||
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"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/gzep"
|
||||
"gitlab.com/manytask/itmo-go/private/tools/testtool"
|
||||
"gitlab.com/slon/shad-go/gzep"
|
||||
"gitlab.com/slon/shad-go/tools/testtool"
|
||||
)
|
||||
|
||||
func BenchmarkEncode(b *testing.B) {
|
||||
|
@ -47,6 +47,7 @@ func TestEncode_RoundTrip(t *testing.T) {
|
|||
require.NoError(t, err, tc.in)
|
||||
require.Equal(t, tc.in, string(out))
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,39 @@
|
|||
|
||||
package hogwarts
|
||||
|
||||
func GetCourseList(prereqs map[string][]string) []string {
|
||||
return []string{}
|
||||
import (
|
||||
"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
|
||||
|
||||
import "math"
|
||||
|
||||
type Guest struct {
|
||||
CheckInDate int
|
||||
CheckOutDate int
|
||||
|
@ -13,5 +15,30 @@ type Load struct {
|
|||
}
|
||||
|
||||
func ComputeLoad(guests []Guest) []Load {
|
||||
return []Load{}
|
||||
if len(guests) == 0 {
|
||||
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"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/illegal"
|
||||
"gitlab.com/manytask/itmo-go/private/illegal/internal"
|
||||
"gitlab.com/slon/shad-go/illegal"
|
||||
"gitlab.com/slon/shad-go/illegal/internal"
|
||||
)
|
||||
|
||||
func TestIllegalField(t *testing.T) {
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/illegal"
|
||||
"gitlab.com/slon/shad-go/illegal"
|
||||
)
|
||||
|
||||
func TestStringFromBytes(t *testing.T) {
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
|
||||
"gitlab.com/manytask/itmo-go/private/iprange"
|
||||
"gitlab.com/slon/shad-go/iprange"
|
||||
)
|
||||
|
||||
func ExampleParseList() {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
В обычном `sync.Mutex` лок всего один. В один момент времени этот лок может находиться
|
||||
у одной горутины. В нашем примитиве локов может быть сколько угодно. Каждый лок мы идентифицируем
|
||||
ключём - строкой. Каждая горутина приходит к нам со списком ключей и хочет захватить сразу
|
||||
ключом - строкой. Каждая горутина приходит к нам со списком ключей и хочет захватить сразу
|
||||
все локи из этого списка. (Наша аналогия с `sync.Mutex` вовсе не значит, что нужно использовать
|
||||
`sync.Mutex` в реализации. Лучше использовать каналы, чтобы проще было реализовать отмену.)
|
||||
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
package keylock_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"slices"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"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{} {
|
||||
|
@ -57,6 +62,21 @@ func TestKeyLock_Progress(t *testing.T) {
|
|||
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) {
|
||||
const N = 10000
|
||||
|
||||
|
@ -116,7 +136,7 @@ func TestKeyLock_SingleKeyStress(t *testing.T) {
|
|||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
for i := 0; i < N; i++ {
|
||||
for j := 0; j < N; j++ {
|
||||
cancelled, unlock := l.LockKeys([]string{"a"}, timeout(time.Millisecond))
|
||||
if !cancelled {
|
||||
unlock()
|
||||
|
@ -127,3 +147,58 @@ func TestKeyLock_SingleKeyStress(t *testing.T) {
|
|||
|
||||
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 (
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"sync"
|
||||
"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) {
|
||||
l := New()
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
@ -30,7 +29,7 @@ func fetch(url string, ch chan<- string) {
|
|||
}
|
||||
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 {
|
||||
ch <- fmt.Sprintf("while reading %s: %v", url, err)
|
||||
return
|
||||
|
|
|
@ -11,8 +11,7 @@
|
|||
|
||||
* Ссылки
|
||||
|
||||
.link https://wiki.yandex.ru/shad/groups/2018/Semester4/GoLang/ Вики страница
|
||||
.link https://gitlab.com/manytask/itmo-go/private Репозиторий
|
||||
.link https://github.com/slon/shad-go Репозиторий
|
||||
.link https://t.me/joinchat/BjrYSxdPJGtJdd1pae08Zg Чат курса в телеграме
|
||||
[[https://p.go.manytask.org]] - эти слайды.
|
||||
|
||||
|
@ -21,7 +20,7 @@
|
|||
- 12+ занятий
|
||||
- Семинарские задания после каждой лекции. *Дедлайн*10*дней.*
|
||||
- 4 _больших_ домашних задания. *Дедлайн*3*недели.*
|
||||
- Критерий оценки: *TODO*.
|
||||
- Критерий оценки: *В*LMS* (>N домашек и >X% за семинары).
|
||||
|
||||
* Hello world
|
||||
|
||||
|
@ -37,12 +36,25 @@ Systems
|
|||
|
||||
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.
|
||||
- Архитектура построена вокруг сервисов, которые общаются по сети.
|
||||
: Скорее вам придётся писать stateless сервис. Statefull сервисы общаются с базой данных по сети.
|
||||
: Скорее вам придётся писать stateless сервис. Stateful сервисы общаются с базой данных по сети.
|
||||
- Многоядерные процессоры даже в телефонах.
|
||||
|
||||
* Скорость разработки
|
||||
|
@ -149,6 +161,8 @@ Language
|
|||
var s = ""
|
||||
var s string = ""
|
||||
|
||||
.link https://go.dev/blog/declaration-syntax Почему тип пишется после названия переменной
|
||||
|
||||
* uniq
|
||||
|
||||
.play -edit uniq/uniq.go
|
||||
|
@ -230,7 +244,7 @@ Pointers
|
|||
|
||||
var s string
|
||||
p := &s
|
||||
s2 = *p
|
||||
s2 := *p
|
||||
|
||||
var p Point
|
||||
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