From 8bb35a6652376739add52d09e3fb82c2393aff84 Mon Sep 17 00:00:00 2001 From: Keith Chong Date: Sun, 28 Mar 2021 22:18:45 -0400 Subject: [PATCH] KAM fails to push gitops configuration to GitLab (767) (#204) Signed-off-by: Keith Chong --- go.mod | 2 +- go.sum | 18 +- vendor/code.gitea.io/sdk/gitea/admin_cron.go | 44 ++ vendor/code.gitea.io/sdk/gitea/admin_org.go | 13 +- vendor/code.gitea.io/sdk/gitea/admin_repo.go | 8 +- vendor/code.gitea.io/sdk/gitea/admin_user.go | 83 +-- vendor/code.gitea.io/sdk/gitea/attachment.go | 37 +- vendor/code.gitea.io/sdk/gitea/client.go | 222 +++++-- vendor/code.gitea.io/sdk/gitea/fork.go | 12 +- vendor/code.gitea.io/sdk/gitea/git_blob.go | 5 +- vendor/code.gitea.io/sdk/gitea/git_hook.go | 24 +- vendor/code.gitea.io/sdk/gitea/go.mod | 4 +- vendor/code.gitea.io/sdk/gitea/go.sum | 2 + vendor/code.gitea.io/sdk/gitea/helper.go | 20 + vendor/code.gitea.io/sdk/gitea/hook.go | 73 ++- vendor/code.gitea.io/sdk/gitea/issue.go | 107 +++- .../code.gitea.io/sdk/gitea/issue_comment.go | 61 +- vendor/code.gitea.io/sdk/gitea/issue_label.go | 108 +++- .../sdk/gitea/issue_milestone.go | 137 ++++- .../code.gitea.io/sdk/gitea/issue_reaction.go | 62 +- .../sdk/gitea/issue_stopwatch.go | 32 +- .../sdk/gitea/issue_subscription.go | 59 +- .../sdk/gitea/issue_tracked_time.go | 94 ++- .../code.gitea.io/sdk/gitea/notifications.go | 140 +++-- vendor/code.gitea.io/sdk/gitea/oauth2.go | 50 +- vendor/code.gitea.io/sdk/gitea/org.go | 106 +++- vendor/code.gitea.io/sdk/gitea/org_member.go | 55 +- vendor/code.gitea.io/sdk/gitea/org_team.go | 150 +++-- vendor/code.gitea.io/sdk/gitea/org_type.go | 27 - vendor/code.gitea.io/sdk/gitea/pull.go | 99 +++- vendor/code.gitea.io/sdk/gitea/pull_review.go | 206 +++++-- vendor/code.gitea.io/sdk/gitea/release.go | 97 +++- vendor/code.gitea.io/sdk/gitea/repo.go | 423 ++++++++++---- vendor/code.gitea.io/sdk/gitea/repo_branch.go | 67 ++- .../sdk/gitea/repo_branch_protection.go | 179 +++--- .../sdk/gitea/repo_collaborator.go | 68 ++- vendor/code.gitea.io/sdk/gitea/repo_commit.go | 31 +- vendor/code.gitea.io/sdk/gitea/repo_file.go | 95 ++- vendor/code.gitea.io/sdk/gitea/repo_key.go | 23 +- .../code.gitea.io/sdk/gitea/repo_migrate.go | 130 +++++ vendor/code.gitea.io/sdk/gitea/repo_refs.go | 28 +- vendor/code.gitea.io/sdk/gitea/repo_stars.go | 81 +++ vendor/code.gitea.io/sdk/gitea/repo_tag.go | 16 +- vendor/code.gitea.io/sdk/gitea/repo_topics.go | 28 +- .../code.gitea.io/sdk/gitea/repo_transfer.go | 11 +- vendor/code.gitea.io/sdk/gitea/repo_tree.go | 5 +- vendor/code.gitea.io/sdk/gitea/repo_watch.go | 42 +- vendor/code.gitea.io/sdk/gitea/settings.go | 74 +++ vendor/code.gitea.io/sdk/gitea/status.go | 25 +- vendor/code.gitea.io/sdk/gitea/user.go | 12 +- vendor/code.gitea.io/sdk/gitea/user_app.go | 42 +- vendor/code.gitea.io/sdk/gitea/user_email.go | 20 +- vendor/code.gitea.io/sdk/gitea/user_follow.go | 44 +- vendor/code.gitea.io/sdk/gitea/user_gpgkey.go | 28 +- vendor/code.gitea.io/sdk/gitea/user_key.go | 28 +- vendor/code.gitea.io/sdk/gitea/user_search.go | 8 +- vendor/code.gitea.io/sdk/gitea/version.go | 51 +- .../hashicorp/go-version/.travis.yml | 13 - .../github.com/hashicorp/go-version/README.md | 3 +- .../hashicorp/go-version/version.go | 8 +- .../jenkins-x/go-scm/pkg/hmac/hmac.go | 4 +- vendor/github.com/jenkins-x/go-scm/scm/app.go | 1 + .../github.com/jenkins-x/go-scm/scm/client.go | 22 +- .../github.com/jenkins-x/go-scm/scm/const.go | 7 + .../github.com/jenkins-x/go-scm/scm/deploy.go | 2 + .../go-scm/scm/driver/bitbucket/bitbucket.go | 16 +- .../go-scm/scm/driver/bitbucket/git.go | 34 +- .../go-scm/scm/driver/bitbucket/issue.go | 28 +- .../go-scm/scm/driver/bitbucket/milestone.go | 31 + .../go-scm/scm/driver/bitbucket/org.go | 25 +- .../go-scm/scm/driver/bitbucket/pr.go | 63 +- .../go-scm/scm/driver/bitbucket/repo.go | 133 ++++- .../go-scm/scm/driver/bitbucket/user.go | 8 + .../go-scm/scm/driver/bitbucket/webhook.go | 109 +++- .../go-scm/scm/driver/fake/content.go | 29 +- .../jenkins-x/go-scm/scm/driver/fake/data.go | 10 + .../go-scm/scm/driver/fake/deploy.go | 110 ++++ .../jenkins-x/go-scm/scm/driver/fake/fake.go | 4 +- .../jenkins-x/go-scm/scm/driver/fake/git.go | 4 + .../jenkins-x/go-scm/scm/driver/fake/issue.go | 8 + .../jenkins-x/go-scm/scm/driver/fake/org.go | 52 +- .../jenkins-x/go-scm/scm/driver/fake/pr.go | 72 ++- .../go-scm/scm/driver/fake/release.go | 108 ++++ .../jenkins-x/go-scm/scm/driver/fake/repo.go | 34 +- .../jenkins-x/go-scm/scm/driver/fake/user.go | 35 +- .../go-scm/scm/driver/gitea/content.go | 86 ++- .../jenkins-x/go-scm/scm/driver/gitea/git.go | 97 +++- .../go-scm/scm/driver/gitea/gitea.go | 73 ++- .../go-scm/scm/driver/gitea/issue.go | 239 ++++---- .../go-scm/scm/driver/gitea/milestone.go | 104 ++++ .../jenkins-x/go-scm/scm/driver/gitea/org.go | 99 +++- .../jenkins-x/go-scm/scm/driver/gitea/pr.go | 98 ++-- .../go-scm/scm/driver/gitea/release.go | 169 ++++++ .../jenkins-x/go-scm/scm/driver/gitea/repo.go | 202 +++---- .../go-scm/scm/driver/gitea/review.go | 118 +++- .../jenkins-x/go-scm/scm/driver/gitea/user.go | 78 +-- .../go-scm/scm/driver/gitea/webhook.go | 203 ++++--- .../go-scm/scm/driver/github/deploy.go | 71 ++- .../jenkins-x/go-scm/scm/driver/github/git.go | 7 + .../go-scm/scm/driver/github/github.go | 14 +- .../go-scm/scm/driver/github/issue.go | 32 + .../go-scm/scm/driver/github/milestone.go | 111 ++++ .../jenkins-x/go-scm/scm/driver/github/org.go | 83 ++- .../jenkins-x/go-scm/scm/driver/github/pr.go | 8 - .../go-scm/scm/driver/github/release.go | 126 ++++ .../go-scm/scm/driver/github/repo.go | 33 +- .../go-scm/scm/driver/github/user.go | 8 + .../go-scm/scm/driver/github/util.go | 32 + .../go-scm/scm/driver/github/webhook.go | 108 ++-- .../go-scm/scm/driver/gitlab/content.go | 33 +- .../jenkins-x/go-scm/scm/driver/gitlab/git.go | 27 +- .../go-scm/scm/driver/gitlab/gitlab.go | 36 +- .../go-scm/scm/driver/gitlab/issue.go | 19 + .../go-scm/scm/driver/gitlab/milestone.go | 166 ++++++ .../jenkins-x/go-scm/scm/driver/gitlab/org.go | 53 +- .../jenkins-x/go-scm/scm/driver/gitlab/pr.go | 119 +++- .../go-scm/scm/driver/gitlab/release.go | 111 ++++ .../go-scm/scm/driver/gitlab/repo.go | 100 +++- .../go-scm/scm/driver/gitlab/user.go | 49 +- .../go-scm/scm/driver/gitlab/util.go | 38 +- .../go-scm/scm/driver/gitlab/webhook.go | 80 ++- .../jenkins-x/go-scm/scm/driver/gogs/git.go | 4 + .../jenkins-x/go-scm/scm/driver/gogs/gogs.go | 8 +- .../jenkins-x/go-scm/scm/driver/gogs/issue.go | 8 + .../go-scm/scm/driver/gogs/milestone.go | 31 + .../jenkins-x/go-scm/scm/driver/gogs/org.go | 20 + .../jenkins-x/go-scm/scm/driver/gogs/pr.go | 8 + .../jenkins-x/go-scm/scm/driver/gogs/repo.go | 4 + .../jenkins-x/go-scm/scm/driver/gogs/user.go | 8 + .../go-scm/scm/driver/gogs/webhook.go | 6 +- .../go-scm/scm/driver/stash/content.go | 3 +- .../jenkins-x/go-scm/scm/driver/stash/git.go | 25 +- .../go-scm/scm/driver/stash/issue.go | 28 +- .../go-scm/scm/driver/stash/milestone.go | 31 + .../jenkins-x/go-scm/scm/driver/stash/org.go | 56 ++ .../jenkins-x/go-scm/scm/driver/stash/pr.go | 39 +- .../jenkins-x/go-scm/scm/driver/stash/repo.go | 15 +- .../go-scm/scm/driver/stash/stash.go | 10 +- .../jenkins-x/go-scm/scm/driver/stash/user.go | 23 +- .../jenkins-x/go-scm/scm/driver/stash/util.go | 6 + .../go-scm/scm/driver/stash/webhook.go | 6 +- .../jenkins-x/go-scm/scm/factory/factory.go | 96 ++- vendor/github.com/jenkins-x/go-scm/scm/git.go | 5 +- .../github.com/jenkins-x/go-scm/scm/issue.go | 7 + .../jenkins-x/go-scm/scm/labels/labels.go | 56 ++ .../jenkins-x/go-scm/scm/milestone.go | 42 ++ vendor/github.com/jenkins-x/go-scm/scm/org.go | 39 ++ vendor/github.com/jenkins-x/go-scm/scm/pr.go | 26 +- .../jenkins-x/go-scm/scm/release.go | 52 ++ .../github.com/jenkins-x/go-scm/scm/repo.go | 4 + .../github.com/jenkins-x/go-scm/scm/review.go | 13 +- .../github.com/jenkins-x/go-scm/scm/user.go | 13 + .../github.com/jenkins-x/go-scm/scm/util.go | 4 +- .../jenkins-x/go-scm/scm/webhook.go | 407 +++++++++---- .../mitchellh/copystructure/.travis.yml | 12 + .../mitchellh/copystructure/LICENSE | 21 + .../mitchellh/copystructure/README.md | 21 + .../mitchellh/copystructure/copier_time.go | 15 + .../mitchellh/copystructure/copystructure.go | 548 ++++++++++++++++++ .../github.com/mitchellh/copystructure/go.mod | 3 + .../github.com/mitchellh/copystructure/go.sum | 2 + .../mitchellh/reflectwalk/.travis.yml | 1 + .../github.com/mitchellh/reflectwalk/LICENSE | 21 + .../mitchellh/reflectwalk/README.md | 6 + .../github.com/mitchellh/reflectwalk/go.mod | 1 + .../mitchellh/reflectwalk/location.go | 19 + .../mitchellh/reflectwalk/location_string.go | 16 + .../mitchellh/reflectwalk/reflectwalk.go | 401 +++++++++++++ vendor/modules.txt | 11 +- 169 files changed, 7843 insertions(+), 2077 deletions(-) create mode 100644 vendor/code.gitea.io/sdk/gitea/admin_cron.go create mode 100644 vendor/code.gitea.io/sdk/gitea/helper.go delete mode 100644 vendor/code.gitea.io/sdk/gitea/org_type.go create mode 100644 vendor/code.gitea.io/sdk/gitea/repo_migrate.go create mode 100644 vendor/code.gitea.io/sdk/gitea/repo_stars.go create mode 100644 vendor/code.gitea.io/sdk/gitea/settings.go delete mode 100644 vendor/github.com/hashicorp/go-version/.travis.yml create mode 100644 vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/milestone.go create mode 100644 vendor/github.com/jenkins-x/go-scm/scm/driver/fake/deploy.go create mode 100644 vendor/github.com/jenkins-x/go-scm/scm/driver/fake/release.go create mode 100644 vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/milestone.go create mode 100644 vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/release.go create mode 100644 vendor/github.com/jenkins-x/go-scm/scm/driver/github/milestone.go create mode 100644 vendor/github.com/jenkins-x/go-scm/scm/driver/github/release.go create mode 100644 vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/milestone.go create mode 100644 vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/release.go create mode 100644 vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/milestone.go create mode 100644 vendor/github.com/jenkins-x/go-scm/scm/driver/stash/milestone.go create mode 100644 vendor/github.com/jenkins-x/go-scm/scm/labels/labels.go create mode 100644 vendor/github.com/jenkins-x/go-scm/scm/milestone.go create mode 100644 vendor/github.com/jenkins-x/go-scm/scm/release.go create mode 100644 vendor/github.com/mitchellh/copystructure/.travis.yml create mode 100644 vendor/github.com/mitchellh/copystructure/LICENSE create mode 100644 vendor/github.com/mitchellh/copystructure/README.md create mode 100644 vendor/github.com/mitchellh/copystructure/copier_time.go create mode 100644 vendor/github.com/mitchellh/copystructure/copystructure.go create mode 100644 vendor/github.com/mitchellh/copystructure/go.mod create mode 100644 vendor/github.com/mitchellh/copystructure/go.sum create mode 100644 vendor/github.com/mitchellh/reflectwalk/.travis.yml create mode 100644 vendor/github.com/mitchellh/reflectwalk/LICENSE create mode 100644 vendor/github.com/mitchellh/reflectwalk/README.md create mode 100644 vendor/github.com/mitchellh/reflectwalk/go.mod create mode 100644 vendor/github.com/mitchellh/reflectwalk/location.go create mode 100644 vendor/github.com/mitchellh/reflectwalk/location_string.go create mode 100644 vendor/github.com/mitchellh/reflectwalk/reflectwalk.go diff --git a/go.mod b/go.mod index 1d3be3b7e..c002fe882 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/google/go-cmp v0.5.2 github.com/h2non/gock v1.0.9 github.com/hinshun/vt10x v0.0.0-20180809195222-d55458df857c // indirect - github.com/jenkins-x/go-scm v1.5.160 + github.com/jenkins-x/go-scm v1.6.6 github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect github.com/mitchellh/go-homedir v1.1.0 github.com/mkmik/multierror v0.3.0 diff --git a/go.sum b/go.sum index 5c9885b68..847720c61 100644 --- a/go.sum +++ b/go.sum @@ -44,8 +44,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.11.0/go.mod h1:/PAbprKS+5msVYogBmczjWalDXnQ9mr64yEq9YnyPeo= -code.gitea.io/sdk/gitea v0.12.1 h1:bMgjEqPnNX/i6TpVwXwpjJtFOnUSuC9P6yy/jjy8sjY= -code.gitea.io/sdk/gitea v0.12.1/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY= +code.gitea.io/sdk/gitea v0.13.1-0.20210217150345-a968e32ca15c h1:GNgYWrJ/Y5doQBjuC1u1HhqgylIgDFR+IS6Mgs20uUk= +code.gitea.io/sdk/gitea v0.13.1-0.20210217150345-a968e32ca15c/go.mod h1:89WiyOX1KEcvjP66sRHdu0RafojGo60bT9UqW17VbWs= contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA= contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0= @@ -655,8 +655,8 @@ github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+ github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= +github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.0.0-20180201235237-0fb14efe8c47/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -690,8 +690,8 @@ github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0 github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= github.com/jenkins-x/go-scm v1.5.79/go.mod h1:PCT338UhP/pQ0IeEeMEf/hoLTYKcH7qjGEKd7jPkeYg= github.com/jenkins-x/go-scm v1.5.117/go.mod h1:PCT338UhP/pQ0IeEeMEf/hoLTYKcH7qjGEKd7jPkeYg= -github.com/jenkins-x/go-scm v1.5.160 h1:1OixAnfXn+3Ymxq3suALpJq7PilmpxKl62S6mO/woXM= -github.com/jenkins-x/go-scm v1.5.160/go.mod h1:wJgj7PfgsCs+YAXC0vEj43g48HKf94apSyza62ADxKY= +github.com/jenkins-x/go-scm v1.6.6 h1:26eY1IjDYOQMUj3YWEwMfDqvAZ4hJqHmmDJSE78Y96o= +github.com/jenkins-x/go-scm v1.6.6/go.mod h1:yVqpMl3ZSkPWVcPi9EhcK3QtTM/anrtYqI//FqwrdxQ= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jimstudt/http-authentication v0.0.0-20140401203705-3eca13d6893a/go.mod h1:wK6yTYYcgjHE1Z1QtXACPDjcFJyBskHEdagmnq3vsP8= github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs= @@ -809,6 +809,7 @@ github.com/mikefarah/yaml/v2 v2.4.0/go.mod h1:ahVqZF4n1W4NqwvVnZzC4es67xsW9uR/RR github.com/mikefarah/yq/v2 v2.4.1/go.mod h1:i8SYf1XdgUvY2OFwSqGAtWOOgimD2McJ6iutoxRm4k0= github.com/mindprince/gonvml v0.0.0-20171110221305-fee913ce8fb2/go.mod h1:2eu9pRWp8mo84xCg6KswZ+USQHjwgRhNp06sozOdsTY= github.com/mistifyio/go-zfs v2.1.1+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= +github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -819,6 +820,7 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/ioprogress v0.0.0-20180201004757-6a23b12fa88e/go.mod h1:waEya8ee1Ro/lgxpVhkJI4BVASzkm3UZqkx/cFJiYHM= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mkmik/multierror v0.3.0 h1:FHr3n5BEVlzlTz8GRbuwimkL2zbdD2gTPcSh0wpRpUg= github.com/mkmik/multierror v0.3.0/go.mod h1:wjBYXRpDhh+8mIp+iLBOq0kZ3Y4ICTncojwvP8LUYLQ= @@ -1271,6 +1273,7 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191021144547-ec77196f6094/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1603,8 +1606,11 @@ gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/h2non/gentleman.v1 v1.0.4/go.mod h1:JYuHVdFzS4MKOXe0o+chKJ4hCe6tqKKw9XH9YP6WFrg= gopkg.in/h2non/gock.v1 v1.0.14 h1:fTeu9fcUvSnLNacYvYI54h+1/XEteDyHvrVCZEEEYNM= gopkg.in/h2non/gock.v1 v1.0.14/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE= +gopkg.in/h2non/gock.v1 v1.0.16 h1:F11k+OafeuFENsjei5t2vMTSTs9L62AdyTe4E1cgdG8= +gopkg.in/h2non/gock.v1 v1.0.16/go.mod h1:XVuDAssexPLwgxCLMvDTWNU5eqklsydR6I5phZ9oPB8= gopkg.in/imdario/mergo.v0 v0.3.7/go.mod h1:9qPP6AGrlC1G2PTNXko614FwGZvorN7MiBU0Eppok+U= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= diff --git a/vendor/code.gitea.io/sdk/gitea/admin_cron.go b/vendor/code.gitea.io/sdk/gitea/admin_cron.go new file mode 100644 index 000000000..99006b696 --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/admin_cron.go @@ -0,0 +1,44 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "fmt" + "time" +) + +// CronTask represents a Cron task +type CronTask struct { + Name string `json:"name"` + Schedule string `json:"schedule"` + Next time.Time `json:"next"` + Prev time.Time `json:"prev"` + ExecTimes int64 `json:"exec_times"` +} + +// ListCronTaskOptions list options for ListCronTasks +type ListCronTaskOptions struct { + ListOptions +} + +// ListCronTasks list available cron tasks +func (c *Client) ListCronTasks(opt ListCronTaskOptions) ([]*CronTask, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil { + return nil, nil, err + } + opt.setDefaults() + ct := make([]*CronTask, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/admin/cron?%s", opt.getURLQuery().Encode()), jsonHeader, nil, &ct) + return ct, resp, err +} + +// RunCronTasks run a cron task +func (c *Client) RunCronTasks(task string) (*Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil { + return nil, err + } + _, resp, err := c.getResponse("POST", fmt.Sprintf("/admin/cron/%s", task), jsonHeader, nil) + return resp, err +} diff --git a/vendor/code.gitea.io/sdk/gitea/admin_org.go b/vendor/code.gitea.io/sdk/gitea/admin_org.go index 8b0bac18f..e572680fc 100644 --- a/vendor/code.gitea.io/sdk/gitea/admin_org.go +++ b/vendor/code.gitea.io/sdk/gitea/admin_org.go @@ -17,19 +17,20 @@ type AdminListOrgsOptions struct { } // AdminListOrgs lists all orgs -func (c *Client) AdminListOrgs(opt AdminListOrgsOptions) ([]*Organization, error) { +func (c *Client) AdminListOrgs(opt AdminListOrgsOptions) ([]*Organization, *Response, error) { opt.setDefaults() orgs := make([]*Organization, 0, opt.PageSize) - return orgs, c.getParsedResponse("GET", fmt.Sprintf("/admin/orgs?%s", opt.getURLQuery().Encode()), nil, nil, &orgs) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/admin/orgs?%s", opt.getURLQuery().Encode()), nil, nil, &orgs) + return orgs, resp, err } // AdminCreateOrg create an organization -func (c *Client) AdminCreateOrg(user string, opt CreateOrgOption) (*Organization, error) { +func (c *Client) AdminCreateOrg(user string, opt CreateOrgOption) (*Organization, *Response, error) { body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } org := new(Organization) - return org, c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/orgs", user), - jsonHeader, bytes.NewReader(body), org) + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/orgs", user), jsonHeader, bytes.NewReader(body), org) + return org, resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/admin_repo.go b/vendor/code.gitea.io/sdk/gitea/admin_repo.go index cf565ffa3..cbd978817 100644 --- a/vendor/code.gitea.io/sdk/gitea/admin_repo.go +++ b/vendor/code.gitea.io/sdk/gitea/admin_repo.go @@ -11,12 +11,12 @@ import ( ) // AdminCreateRepo create a repo -func (c *Client) AdminCreateRepo(user string, opt CreateRepoOption) (*Repository, error) { +func (c *Client) AdminCreateRepo(user string, opt CreateRepoOption) (*Repository, *Response, error) { body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } repo := new(Repository) - return repo, c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/repos", user), - jsonHeader, bytes.NewReader(body), repo) + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/repos", user), jsonHeader, bytes.NewReader(body), repo) + return repo, resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/admin_user.go b/vendor/code.gitea.io/sdk/gitea/admin_user.go index c44793439..a24f26038 100644 --- a/vendor/code.gitea.io/sdk/gitea/admin_user.go +++ b/vendor/code.gitea.io/sdk/gitea/admin_user.go @@ -17,10 +17,11 @@ type AdminListUsersOptions struct { } // AdminListUsers lists all users -func (c *Client) AdminListUsers(opt AdminListUsersOptions) ([]*User, error) { +func (c *Client) AdminListUsers(opt AdminListUsersOptions) ([]*User, *Response, error) { opt.setDefaults() users := make([]*User, 0, opt.PageSize) - return users, c.getParsedResponse("GET", fmt.Sprintf("/admin/users?%s", opt.getURLQuery().Encode()), nil, nil, &users) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/admin/users?%s", opt.getURLQuery().Encode()), nil, nil, &users) + return users, resp, err } // CreateUserOption create user options @@ -35,63 +36,79 @@ type CreateUserOption struct { SendNotify bool `json:"send_notify"` } +// Validate the CreateUserOption struct +func (opt CreateUserOption) Validate() error { + if len(opt.Email) == 0 { + return fmt.Errorf("email is empty") + } + if len(opt.Username) == 0 { + return fmt.Errorf("username is empty") + } + return nil +} + // AdminCreateUser create a user -func (c *Client) AdminCreateUser(opt CreateUserOption) (*User, error) { +func (c *Client) AdminCreateUser(opt CreateUserOption) (*User, *Response, error) { + if err := opt.Validate(); err != nil { + return nil, nil, err + } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } user := new(User) - return user, c.getParsedResponse("POST", "/admin/users", jsonHeader, bytes.NewReader(body), user) + resp, err := c.getParsedResponse("POST", "/admin/users", jsonHeader, bytes.NewReader(body), user) + return user, resp, err } // EditUserOption edit user options type EditUserOption struct { - SourceID int64 `json:"source_id"` - LoginName string `json:"login_name"` - FullName string `json:"full_name"` - Email string `json:"email"` - Password string `json:"password"` - MustChangePassword *bool `json:"must_change_password"` - Website string `json:"website"` - Location string `json:"location"` - Active *bool `json:"active"` - Admin *bool `json:"admin"` - AllowGitHook *bool `json:"allow_git_hook"` - AllowImportLocal *bool `json:"allow_import_local"` - MaxRepoCreation *int `json:"max_repo_creation"` - ProhibitLogin *bool `json:"prohibit_login"` - AllowCreateOrganization *bool `json:"allow_create_organization"` + SourceID int64 `json:"source_id"` + LoginName string `json:"login_name"` + Email *string `json:"email"` + FullName *string `json:"full_name"` + Password string `json:"password"` + MustChangePassword *bool `json:"must_change_password"` + Website *string `json:"website"` + Location *string `json:"location"` + Active *bool `json:"active"` + Admin *bool `json:"admin"` + AllowGitHook *bool `json:"allow_git_hook"` + AllowImportLocal *bool `json:"allow_import_local"` + MaxRepoCreation *int `json:"max_repo_creation"` + ProhibitLogin *bool `json:"prohibit_login"` + AllowCreateOrganization *bool `json:"allow_create_organization"` } // AdminEditUser modify user informations -func (c *Client) AdminEditUser(user string, opt EditUserOption) error { +func (c *Client) AdminEditUser(user string, opt EditUserOption) (*Response, error) { body, err := json.Marshal(&opt) if err != nil { - return err + return nil, err } - _, err = c.getResponse("PATCH", fmt.Sprintf("/admin/users/%s", user), jsonHeader, bytes.NewReader(body)) - return err + _, resp, err := c.getResponse("PATCH", fmt.Sprintf("/admin/users/%s", user), jsonHeader, bytes.NewReader(body)) + return resp, err } // AdminDeleteUser delete one user according name -func (c *Client) AdminDeleteUser(user string) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/admin/users/%s", user), nil, nil) - return err +func (c *Client) AdminDeleteUser(user string) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/admin/users/%s", user), nil, nil) + return resp, err } // AdminCreateUserPublicKey adds a public key for the user -func (c *Client) AdminCreateUserPublicKey(user string, opt CreateKeyOption) (*PublicKey, error) { +func (c *Client) AdminCreateUserPublicKey(user string, opt CreateKeyOption) (*PublicKey, *Response, error) { body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } key := new(PublicKey) - return key, c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/keys", user), jsonHeader, bytes.NewReader(body), key) + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/keys", user), jsonHeader, bytes.NewReader(body), key) + return key, resp, err } // AdminDeleteUserPublicKey deletes a user's public key -func (c *Client) AdminDeleteUserPublicKey(user string, keyID int) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/admin/users/%s/keys/%d", user, keyID), nil, nil) - return err +func (c *Client) AdminDeleteUserPublicKey(user string, keyID int) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/admin/users/%s/keys/%d", user, keyID), nil, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/attachment.go b/vendor/code.gitea.io/sdk/gitea/attachment.go index a13787be8..6f67ae3de 100644 --- a/vendor/code.gitea.io/sdk/gitea/attachment.go +++ b/vendor/code.gitea.io/sdk/gitea/attachment.go @@ -30,47 +30,47 @@ type ListReleaseAttachmentsOptions struct { } // ListReleaseAttachments list release's attachments -func (c *Client) ListReleaseAttachments(user, repo string, release int64, opt ListReleaseAttachmentsOptions) ([]*Attachment, error) { +func (c *Client) ListReleaseAttachments(user, repo string, release int64, opt ListReleaseAttachmentsOptions) ([]*Attachment, *Response, error) { opt.setDefaults() attachments := make([]*Attachment, 0, opt.PageSize) - err := c.getParsedResponse("GET", + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/releases/%d/assets?%s", user, repo, release, opt.getURLQuery().Encode()), nil, nil, &attachments) - return attachments, err + return attachments, resp, err } // GetReleaseAttachment returns the requested attachment -func (c *Client) GetReleaseAttachment(user, repo string, release int64, id int64) (*Attachment, error) { +func (c *Client) GetReleaseAttachment(user, repo string, release int64, id int64) (*Attachment, *Response, error) { a := new(Attachment) - err := c.getParsedResponse("GET", + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, id), nil, nil, &a) - return a, err + return a, resp, err } // CreateReleaseAttachment creates an attachment for the given release -func (c *Client) CreateReleaseAttachment(user, repo string, release int64, file io.Reader, filename string) (*Attachment, error) { +func (c *Client) CreateReleaseAttachment(user, repo string, release int64, file io.Reader, filename string) (*Attachment, *Response, error) { // Write file to body body := new(bytes.Buffer) writer := multipart.NewWriter(body) part, err := writer.CreateFormFile("attachment", filename) if err != nil { - return nil, err + return nil, nil, err } if _, err = io.Copy(part, file); err != nil { - return nil, err + return nil, nil, err } if err = writer.Close(); err != nil { - return nil, err + return nil, nil, err } // Send request attachment := new(Attachment) - err = c.getParsedResponse("POST", + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/releases/%d/assets", user, repo, release), http.Header{"Content-Type": {writer.FormDataContentType()}}, body, &attachment) - return attachment, err + return attachment, resp, err } // EditAttachmentOptions options for editing attachments @@ -79,17 +79,18 @@ type EditAttachmentOptions struct { } // EditReleaseAttachment updates the given attachment with the given options -func (c *Client) EditReleaseAttachment(user, repo string, release int64, attachment int64, form EditAttachmentOptions) (*Attachment, error) { +func (c *Client) EditReleaseAttachment(user, repo string, release int64, attachment int64, form EditAttachmentOptions) (*Attachment, *Response, error) { body, err := json.Marshal(&form) if err != nil { - return nil, err + return nil, nil, err } attach := new(Attachment) - return attach, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, attachment), jsonHeader, bytes.NewReader(body), attach) + resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, attachment), jsonHeader, bytes.NewReader(body), attach) + return attach, resp, err } // DeleteReleaseAttachment deletes the given attachment including the uploaded file -func (c *Client) DeleteReleaseAttachment(user, repo string, release int64, id int64) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, id), nil, nil) - return err +func (c *Client) DeleteReleaseAttachment(user, repo string, release int64, id int64) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, id), nil, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/client.go b/vendor/code.gitea.io/sdk/gitea/client.go index 04f6a4cf2..6e579e8be 100644 --- a/vendor/code.gitea.io/sdk/gitea/client.go +++ b/vendor/code.gitea.io/sdk/gitea/client.go @@ -6,6 +6,7 @@ package gitea import ( + "context" "encoding/json" "errors" "fmt" @@ -22,60 +23,152 @@ var jsonHeader = http.Header{"content-type": []string{"application/json"}} // Version return the library version func Version() string { - return "0.12.0" + return "0.14.0" } // Client represents a Gitea API client. type Client struct { - url string - accessToken string - username string - password string - otp string - sudo string - client *http.Client - serverVersion *version.Version - versionLock sync.RWMutex + url string + accessToken string + username string + password string + otp string + sudo string + debug bool + client *http.Client + ctx context.Context + serverVersion *version.Version + getVersionOnce sync.Once +} + +// Response represents the gitea response +type Response struct { + *http.Response } // NewClient initializes and returns a API client. -func NewClient(url, token string) *Client { - return &Client{ - url: strings.TrimSuffix(url, "/"), - accessToken: token, - client: &http.Client{}, +func NewClient(url string, options ...func(*Client)) (*Client, error) { + client := &Client{ + url: strings.TrimSuffix(url, "/"), + client: &http.Client{}, + ctx: context.Background(), + } + for _, opt := range options { + opt(client) + } + if err := client.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil { + return nil, err } + return client, nil } // NewClientWithHTTP creates an API client with a custom http client +// Deprecated use SetHTTPClient option func NewClientWithHTTP(url string, httpClient *http.Client) *Client { - client := NewClient(url, "") - client.client = httpClient + client, _ := NewClient(url, SetHTTPClient(httpClient)) return client } -// SetBasicAuth sets basicauth +// SetHTTPClient is an option for NewClient to set custom http client +func SetHTTPClient(httpClient *http.Client) func(client *Client) { + return func(client *Client) { + client.client = httpClient + } +} + +// SetToken is an option for NewClient to set token +func SetToken(token string) func(client *Client) { + return func(client *Client) { + client.accessToken = token + } +} + +// SetBasicAuth is an option for NewClient to set username and password +func SetBasicAuth(username, password string) func(client *Client) { + return func(client *Client) { + client.SetBasicAuth(username, password) + } +} + +// SetBasicAuth sets username and password func (c *Client) SetBasicAuth(username, password string) { c.username, c.password = username, password } +// SetOTP is an option for NewClient to set OTP for 2FA +func SetOTP(otp string) func(client *Client) { + return func(client *Client) { + client.SetOTP(otp) + } +} + // SetOTP sets OTP for 2FA func (c *Client) SetOTP(otp string) { c.otp = otp } +// SetContext is an option for NewClient to set context +func SetContext(ctx context.Context) func(client *Client) { + return func(client *Client) { + client.SetContext(ctx) + } +} + +// SetContext set context witch is used for http requests +func (c *Client) SetContext(ctx context.Context) { + c.ctx = ctx +} + // SetHTTPClient replaces default http.Client with user given one. func (c *Client) SetHTTPClient(client *http.Client) { c.client = client } +// SetSudo is an option for NewClient to set sudo header +func SetSudo(sudo string) func(client *Client) { + return func(client *Client) { + client.SetSudo(sudo) + } +} + // SetSudo sets username to impersonate. func (c *Client) SetSudo(sudo string) { c.sudo = sudo } -func (c *Client) doRequest(method, path string, header http.Header, body io.Reader) (*http.Response, error) { - req, err := http.NewRequest(method, c.url+"/api/v1"+path, body) +// SetDebugMode is an option for NewClient to enable debug mode +func SetDebugMode() func(client *Client) { + return func(client *Client) { + client.debug = true + } +} + +func (c *Client) getWebResponse(method, path string, body io.Reader) ([]byte, *Response, error) { + if c.debug { + fmt.Printf("%s: %s\nBody: %v\n", method, c.url+path, body) + } + req, err := http.NewRequestWithContext(c.ctx, method, c.url+path, body) + if err != nil { + return nil, nil, err + } + resp, err := c.client.Do(req) + if err != nil { + return nil, nil, err + } + + defer resp.Body.Close() + data, err := ioutil.ReadAll(resp.Body) + if c.debug { + fmt.Printf("Response: %v\n\n", resp) + } + return data, &Response{resp}, nil +} + +func (c *Client) doRequest(method, path string, header http.Header, body io.Reader) (*Response, error) { + if c.debug { + fmt.Printf("%s: %s\nHeader: %v\nBody: %s\n", method, c.url+"/api/v1"+path, header, body) + } + req, err := http.NewRequestWithContext(c.ctx, method, c.url+"/api/v1"+path, body) if err != nil { return nil, err } @@ -95,59 +188,94 @@ func (c *Client) doRequest(method, path string, header http.Header, body io.Read req.Header[k] = v } - return c.client.Do(req) -} - -func (c *Client) getResponse(method, path string, header http.Header, body io.Reader) ([]byte, error) { - resp, err := c.doRequest(method, path, header, body) + resp, err := c.client.Do(req) if err != nil { return nil, err } - defer resp.Body.Close() + if c.debug { + fmt.Printf("Response: %v\n\n", resp) + } + return &Response{resp}, nil +} +// Converts a response for a HTTP status code indicating an error condition +// (non-2XX) to a well-known error value and response body. For non-problematic +// (2XX) status codes nil will be returned. Note that on a non-2XX response, the +// response body stream will have been read and, hence, is closed on return. +func statusCodeToErr(resp *Response) (body []byte, err error) { + // no error + if resp.StatusCode/100 == 2 { + return nil, nil + } + + // + // error: body will be read for details + // + defer resp.Body.Close() data, err := ioutil.ReadAll(resp.Body) if err != nil { - return nil, err + return nil, fmt.Errorf("body read on HTTP error %d: %v", resp.StatusCode, err) } switch resp.StatusCode { case 403: - return nil, errors.New("403 Forbidden") + return data, errors.New("403 Forbidden") case 404: - return nil, errors.New("404 Not Found") + return data, errors.New("404 Not Found") case 409: - return nil, errors.New("409 Conflict") + return data, errors.New("409 Conflict") case 422: - return nil, fmt.Errorf("422 Unprocessable Entity: %s", string(data)) + return data, fmt.Errorf("422 Unprocessable Entity: %s", string(data)) + } + + path := resp.Request.URL.Path + method := resp.Request.Method + header := resp.Request.Header + errMap := make(map[string]interface{}) + if err = json.Unmarshal(data, &errMap); err != nil { + // when the JSON can't be parsed, data was probably empty or a + // plain string, so we try to return a helpful error anyway + return data, fmt.Errorf("Unknown API Error: %d\nRequest: '%s' with '%s' method '%s' header and '%s' body", resp.StatusCode, path, method, header, string(data)) } + return data, errors.New(errMap["message"].(string)) +} - if resp.StatusCode/100 != 2 { - errMap := make(map[string]interface{}) - if err = json.Unmarshal(data, &errMap); err != nil { - // when the JSON can't be parsed, data was probably empty or a plain string, - // so we try to return a helpful error anyway - return nil, fmt.Errorf("Unknown API Error: %d\nRequest: '%s' with '%s' method '%s' header and '%s' body", resp.StatusCode, path, method, header, string(data)) - } - return nil, errors.New(errMap["message"].(string)) +func (c *Client) getResponse(method, path string, header http.Header, body io.Reader) ([]byte, *Response, error) { + resp, err := c.doRequest(method, path, header, body) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + // check for errors + data, err := statusCodeToErr(resp) + if err != nil { + return data, resp, err + } + + // success (2XX), read body + data, err = ioutil.ReadAll(resp.Body) + if err != nil { + return nil, resp, err } - return data, nil + return data, resp, nil } -func (c *Client) getParsedResponse(method, path string, header http.Header, body io.Reader, obj interface{}) error { - data, err := c.getResponse(method, path, header, body) +func (c *Client) getParsedResponse(method, path string, header http.Header, body io.Reader, obj interface{}) (*Response, error) { + data, resp, err := c.getResponse(method, path, header, body) if err != nil { - return err + return resp, err } - return json.Unmarshal(data, obj) + return resp, json.Unmarshal(data, obj) } -func (c *Client) getStatusCode(method, path string, header http.Header, body io.Reader) (int, error) { +func (c *Client) getStatusCode(method, path string, header http.Header, body io.Reader) (int, *Response, error) { resp, err := c.doRequest(method, path, header, body) if err != nil { - return -1, err + return -1, resp, err } defer resp.Body.Close() - return resp.StatusCode, nil + return resp.StatusCode, resp, nil } diff --git a/vendor/code.gitea.io/sdk/gitea/fork.go b/vendor/code.gitea.io/sdk/gitea/fork.go index fe197462c..a5197125d 100644 --- a/vendor/code.gitea.io/sdk/gitea/fork.go +++ b/vendor/code.gitea.io/sdk/gitea/fork.go @@ -16,12 +16,13 @@ type ListForksOptions struct { } // ListForks list a repository's forks -func (c *Client) ListForks(user string, repo string, opt ListForksOptions) ([]*Repository, error) { +func (c *Client) ListForks(user string, repo string, opt ListForksOptions) ([]*Repository, *Response, error) { opt.setDefaults() forks := make([]*Repository, opt.PageSize) - return forks, c.getParsedResponse("GET", + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/forks?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &forks) + return forks, resp, err } // CreateForkOption options for creating a fork @@ -31,11 +32,12 @@ type CreateForkOption struct { } // CreateFork create a fork of a repository -func (c *Client) CreateFork(user, repo string, form CreateForkOption) (*Repository, error) { +func (c *Client) CreateFork(user, repo string, form CreateForkOption) (*Repository, *Response, error) { body, err := json.Marshal(form) if err != nil { - return nil, err + return nil, nil, err } fork := new(Repository) - return fork, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/forks", user, repo), jsonHeader, bytes.NewReader(body), &fork) + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/forks", user, repo), jsonHeader, bytes.NewReader(body), &fork) + return fork, resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/git_blob.go b/vendor/code.gitea.io/sdk/gitea/git_blob.go index 2843bc358..262fd92df 100644 --- a/vendor/code.gitea.io/sdk/gitea/git_blob.go +++ b/vendor/code.gitea.io/sdk/gitea/git_blob.go @@ -18,7 +18,8 @@ type GitBlobResponse struct { } // GetBlob get the blob of a repository file -func (c *Client) GetBlob(user, repo, sha string) (*GitBlobResponse, error) { +func (c *Client) GetBlob(user, repo, sha string) (*GitBlobResponse, *Response, error) { blob := new(GitBlobResponse) - return blob, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/blobs/%s", user, repo, sha), nil, nil, blob) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/blobs/%s", user, repo, sha), nil, nil, blob) + return blob, resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/git_hook.go b/vendor/code.gitea.io/sdk/gitea/git_hook.go index 1162d0911..520ce538e 100644 --- a/vendor/code.gitea.io/sdk/gitea/git_hook.go +++ b/vendor/code.gitea.io/sdk/gitea/git_hook.go @@ -23,16 +23,18 @@ type ListRepoGitHooksOptions struct { } // ListRepoGitHooks list all the Git hooks of one repository -func (c *Client) ListRepoGitHooks(user, repo string, opt ListRepoGitHooksOptions) ([]*GitHook, error) { +func (c *Client) ListRepoGitHooks(user, repo string, opt ListRepoGitHooksOptions) ([]*GitHook, *Response, error) { opt.setDefaults() hooks := make([]*GitHook, 0, opt.PageSize) - return hooks, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/git?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &hooks) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/git?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &hooks) + return hooks, resp, err } // GetRepoGitHook get a Git hook of a repository -func (c *Client) GetRepoGitHook(user, repo, id string) (*GitHook, error) { +func (c *Client) GetRepoGitHook(user, repo, id string) (*GitHook, *Response, error) { h := new(GitHook) - return h, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), nil, nil, h) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), nil, nil, h) + return h, resp, err } // EditGitHookOption options when modifying one Git hook @@ -41,17 +43,17 @@ type EditGitHookOption struct { } // EditRepoGitHook modify one Git hook of a repository -func (c *Client) EditRepoGitHook(user, repo, id string, opt EditGitHookOption) error { +func (c *Client) EditRepoGitHook(user, repo, id string, opt EditGitHookOption) (*Response, error) { body, err := json.Marshal(&opt) if err != nil { - return err + return nil, err } - _, err = c.getResponse("PATCH", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), jsonHeader, bytes.NewReader(body)) - return err + _, resp, err := c.getResponse("PATCH", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), jsonHeader, bytes.NewReader(body)) + return resp, err } // DeleteRepoGitHook delete one Git hook from a repository -func (c *Client) DeleteRepoGitHook(user, repo, id string) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), nil, nil) - return err +func (c *Client) DeleteRepoGitHook(user, repo, id string) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), nil, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/go.mod b/vendor/code.gitea.io/sdk/gitea/go.mod index 7b0d75fd3..ac2a262ab 100644 --- a/vendor/code.gitea.io/sdk/gitea/go.mod +++ b/vendor/code.gitea.io/sdk/gitea/go.mod @@ -1,8 +1,8 @@ module code.gitea.io/sdk/gitea -go 1.12 +go 1.13 require ( - github.com/hashicorp/go-version v1.2.0 + github.com/hashicorp/go-version v1.2.1 github.com/stretchr/testify v1.4.0 ) diff --git a/vendor/code.gitea.io/sdk/gitea/go.sum b/vendor/code.gitea.io/sdk/gitea/go.sum index e210c1c42..82997d0cc 100644 --- a/vendor/code.gitea.io/sdk/gitea/go.sum +++ b/vendor/code.gitea.io/sdk/gitea/go.sum @@ -2,6 +2,8 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= +github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/vendor/code.gitea.io/sdk/gitea/helper.go b/vendor/code.gitea.io/sdk/gitea/helper.go new file mode 100644 index 000000000..ff8038b12 --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/helper.go @@ -0,0 +1,20 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +// OptionalBool convert a bool to a bool reference +func OptionalBool(v bool) *bool { + return &v +} + +// OptionalString convert a string to a string reference +func OptionalString(v string) *string { + return &v +} + +// OptionalInt64 convert a int64 to a int64 reference +func OptionalInt64(v int64) *int64 { + return &v +} diff --git a/vendor/code.gitea.io/sdk/gitea/hook.go b/vendor/code.gitea.io/sdk/gitea/hook.go index f89a6e952..3a6be65ef 100644 --- a/vendor/code.gitea.io/sdk/gitea/hook.go +++ b/vendor/code.gitea.io/sdk/gitea/hook.go @@ -30,29 +30,33 @@ type ListHooksOptions struct { } // ListOrgHooks list all the hooks of one organization -func (c *Client) ListOrgHooks(org string, opt ListHooksOptions) ([]*Hook, error) { +func (c *Client) ListOrgHooks(org string, opt ListHooksOptions) ([]*Hook, *Response, error) { opt.setDefaults() hooks := make([]*Hook, 0, opt.PageSize) - return hooks, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/hooks?%s", org, opt.getURLQuery().Encode()), nil, nil, &hooks) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/hooks?%s", org, opt.getURLQuery().Encode()), nil, nil, &hooks) + return hooks, resp, err } // ListRepoHooks list all the hooks of one repository -func (c *Client) ListRepoHooks(user, repo string, opt ListHooksOptions) ([]*Hook, error) { +func (c *Client) ListRepoHooks(user, repo string, opt ListHooksOptions) ([]*Hook, *Response, error) { opt.setDefaults() hooks := make([]*Hook, 0, opt.PageSize) - return hooks, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &hooks) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &hooks) + return hooks, resp, err } // GetOrgHook get a hook of an organization -func (c *Client) GetOrgHook(org string, id int64) (*Hook, error) { +func (c *Client) GetOrgHook(org string, id int64) (*Hook, *Response, error) { h := new(Hook) - return h, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), nil, nil, h) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), nil, nil, h) + return h, resp, err } // GetRepoHook get a hook of a repository -func (c *Client) GetRepoHook(user, repo string, id int64) (*Hook, error) { +func (c *Client) GetRepoHook(user, repo string, id int64) (*Hook, *Response, error) { h := new(Hook) - return h, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), nil, nil, h) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), nil, nil, h) + return h, resp, err } // CreateHookOption options when create a hook @@ -64,24 +68,37 @@ type CreateHookOption struct { Active bool `json:"active"` } +// Validate the CreateHookOption struct +func (opt CreateHookOption) Validate() error { + if len(opt.Type) == 0 { + return fmt.Errorf("hook type needed") + } + return nil +} + // CreateOrgHook create one hook for an organization, with options -func (c *Client) CreateOrgHook(org string, opt CreateHookOption) (*Hook, error) { +func (c *Client) CreateOrgHook(org string, opt CreateHookOption) (*Hook, *Response, error) { + if err := opt.Validate(); err != nil { + return nil, nil, err + } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } h := new(Hook) - return h, c.getParsedResponse("POST", fmt.Sprintf("/orgs/%s/hooks", org), jsonHeader, bytes.NewReader(body), h) + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/orgs/%s/hooks", org), jsonHeader, bytes.NewReader(body), h) + return h, resp, err } // CreateRepoHook create one hook for a repository, with options -func (c *Client) CreateRepoHook(user, repo string, opt CreateHookOption) (*Hook, error) { +func (c *Client) CreateRepoHook(user, repo string, opt CreateHookOption) (*Hook, *Response, error) { body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } h := new(Hook) - return h, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/hooks", user, repo), jsonHeader, bytes.NewReader(body), h) + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/hooks", user, repo), jsonHeader, bytes.NewReader(body), h) + return h, resp, err } // EditHookOption options when modify one hook @@ -93,33 +110,33 @@ type EditHookOption struct { } // EditOrgHook modify one hook of an organization, with hook id and options -func (c *Client) EditOrgHook(org string, id int64, opt EditHookOption) error { +func (c *Client) EditOrgHook(org string, id int64, opt EditHookOption) (*Response, error) { body, err := json.Marshal(&opt) if err != nil { - return err + return nil, err } - _, err = c.getResponse("PATCH", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), jsonHeader, bytes.NewReader(body)) - return err + _, resp, err := c.getResponse("PATCH", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), jsonHeader, bytes.NewReader(body)) + return resp, err } // EditRepoHook modify one hook of a repository, with hook id and options -func (c *Client) EditRepoHook(user, repo string, id int64, opt EditHookOption) error { +func (c *Client) EditRepoHook(user, repo string, id int64, opt EditHookOption) (*Response, error) { body, err := json.Marshal(&opt) if err != nil { - return err + return nil, err } - _, err = c.getResponse("PATCH", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), jsonHeader, bytes.NewReader(body)) - return err + _, resp, err := c.getResponse("PATCH", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), jsonHeader, bytes.NewReader(body)) + return resp, err } // DeleteOrgHook delete one hook from an organization, with hook id -func (c *Client) DeleteOrgHook(org string, id int64) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), nil, nil) - return err +func (c *Client) DeleteOrgHook(org string, id int64) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), nil, nil) + return resp, err } // DeleteRepoHook delete one hook from a repository, with hook id -func (c *Client) DeleteRepoHook(user, repo string, id int64) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), nil, nil) - return err +func (c *Client) DeleteRepoHook(user, repo string, id int64) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), nil, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/issue.go b/vendor/code.gitea.io/sdk/gitea/issue.go index 0e57147f1..a5280e7a7 100644 --- a/vendor/code.gitea.io/sdk/gitea/issue.go +++ b/vendor/code.gitea.io/sdk/gitea/issue.go @@ -32,18 +32,23 @@ type RepositoryMeta struct { type Issue struct { ID int64 `json:"id"` URL string `json:"url"` + HTMLURL string `json:"html_url"` Index int64 `json:"number"` Poster *User `json:"user"` OriginalAuthor string `json:"original_author"` OriginalAuthorID int64 `json:"original_author_id"` Title string `json:"title"` Body string `json:"body"` + Ref string `json:"ref"` Labels []*Label `json:"labels"` Milestone *Milestone `json:"milestone"` - Assignee *User `json:"assignee"` - Assignees []*User `json:"assignees"` + // deprecated + // TODO: rm on sdk 0.15.0 + Assignee *User `json:"assignee"` + Assignees []*User `json:"assignees"` // Whether the issue is open or closed State StateType `json:"state"` + IsLocked bool `json:"is_locked"` Comments int `json:"comments"` Created time.Time `json:"created_at"` Updated time.Time `json:"updated_at"` @@ -113,56 +118,65 @@ func (opt *ListIssueOption) QueryEncode() string { } // ListIssues returns all issues assigned the authenticated user -func (c *Client) ListIssues(opt ListIssueOption) ([]*Issue, error) { +func (c *Client) ListIssues(opt ListIssueOption) ([]*Issue, *Response, error) { opt.setDefaults() issues := make([]*Issue, 0, opt.PageSize) link, _ := url.Parse("/repos/issues/search") link.RawQuery = opt.QueryEncode() - err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &issues) - if e := c.CheckServerVersionConstraint(">=1.12.0"); e != nil { + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &issues) + if e := c.checkServerVersionGreaterThanOrEqual(version1_12_0); e != nil { for i := 0; i < len(issues); i++ { if issues[i].Repository != nil { issues[i].Repository.Owner = strings.Split(issues[i].Repository.FullName, "/")[0] } } } - return issues, err + for i := range issues { + c.issueBackwardsCompatibility(issues[i]) + } + return issues, resp, err } // ListRepoIssues returns all issues for a given repository -func (c *Client) ListRepoIssues(owner, repo string, opt ListIssueOption) ([]*Issue, error) { +func (c *Client) ListRepoIssues(owner, repo string, opt ListIssueOption) ([]*Issue, *Response, error) { opt.setDefaults() issues := make([]*Issue, 0, opt.PageSize) link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues", owner, repo)) link.RawQuery = opt.QueryEncode() - err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &issues) - if e := c.CheckServerVersionConstraint(">=1.12.0"); e != nil { + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &issues) + if e := c.checkServerVersionGreaterThanOrEqual(version1_12_0); e != nil { for i := 0; i < len(issues); i++ { if issues[i].Repository != nil { issues[i].Repository.Owner = strings.Split(issues[i].Repository.FullName, "/")[0] } } } - return issues, err + for i := range issues { + c.issueBackwardsCompatibility(issues[i]) + } + return issues, resp, err } // GetIssue returns a single issue for a given repository -func (c *Client) GetIssue(owner, repo string, index int64) (*Issue, error) { +func (c *Client) GetIssue(owner, repo string, index int64) (*Issue, *Response, error) { issue := new(Issue) - err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index), nil, nil, issue) - if e := c.CheckServerVersionConstraint(">=1.12.0"); e != nil && issue.Repository != nil { + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index), nil, nil, issue) + if e := c.checkServerVersionGreaterThanOrEqual(version1_12_0); e != nil && issue.Repository != nil { issue.Repository.Owner = strings.Split(issue.Repository.FullName, "/")[0] } - return issue, err + c.issueBackwardsCompatibility(issue) + return issue, resp, err } // CreateIssueOption options to create one issue type CreateIssueOption struct { Title string `json:"title"` Body string `json:"body"` - // username of assignee + Ref string `json:"ref"` + // deprecated + // TODO: rm on sdk 0.15.0 Assignee string `json:"assignee"` Assignees []string `json:"assignees"` Deadline *time.Time `json:"due_date"` @@ -173,35 +187,72 @@ type CreateIssueOption struct { Closed bool `json:"closed"` } +// Validate the CreateIssueOption struct +func (opt CreateIssueOption) Validate() error { + if len(strings.TrimSpace(opt.Title)) == 0 { + return fmt.Errorf("title is empty") + } + return nil +} + // CreateIssue create a new issue for a given repository -func (c *Client) CreateIssue(owner, repo string, opt CreateIssueOption) (*Issue, error) { +func (c *Client) CreateIssue(owner, repo string, opt CreateIssueOption) (*Issue, *Response, error) { + if err := opt.Validate(); err != nil { + return nil, nil, err + } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } issue := new(Issue) - return issue, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues", owner, repo), + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues", owner, repo), jsonHeader, bytes.NewReader(body), issue) + c.issueBackwardsCompatibility(issue) + return issue, resp, err } // EditIssueOption options for editing an issue type EditIssueOption struct { - Title string `json:"title"` - Body *string `json:"body"` - Assignee *string `json:"assignee"` - Assignees []string `json:"assignees"` - Milestone *int64 `json:"milestone"` - State *StateType `json:"state"` - Deadline *time.Time `json:"due_date"` + Title string `json:"title"` + Body *string `json:"body"` + Ref *string `json:"ref"` + // deprecated + // TODO: rm on sdk 0.15.0 + Assignee *string `json:"assignee"` + Assignees []string `json:"assignees"` + Milestone *int64 `json:"milestone"` + State *StateType `json:"state"` + Deadline *time.Time `json:"due_date"` + RemoveDeadline *bool `json:"unset_due_date"` +} + +// Validate the EditIssueOption struct +func (opt EditIssueOption) Validate() error { + if len(opt.Title) != 0 && len(strings.TrimSpace(opt.Title)) == 0 { + return fmt.Errorf("title is empty") + } + return nil } // EditIssue modify an existing issue for a given repository -func (c *Client) EditIssue(owner, repo string, index int64, opt EditIssueOption) (*Issue, error) { +func (c *Client) EditIssue(owner, repo string, index int64, opt EditIssueOption) (*Issue, *Response, error) { + if err := opt.Validate(); err != nil { + return nil, nil, err + } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } issue := new(Issue) - return issue, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index), + resp, err := c.getParsedResponse("PATCH", + fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index), jsonHeader, bytes.NewReader(body), issue) + c.issueBackwardsCompatibility(issue) + return issue, resp, err +} + +func (c *Client) issueBackwardsCompatibility(issue *Issue) { + if c.checkServerVersionGreaterThanOrEqual(version1_12_0) != nil { + issue.HTMLURL = fmt.Sprintf("%s/%s/issues/%d", c.url, issue.Repository.FullName, issue.Index) + } } diff --git a/vendor/code.gitea.io/sdk/gitea/issue_comment.go b/vendor/code.gitea.io/sdk/gitea/issue_comment.go index cc8cf9fbd..4eff850d1 100644 --- a/vendor/code.gitea.io/sdk/gitea/issue_comment.go +++ b/vendor/code.gitea.io/sdk/gitea/issue_comment.go @@ -46,30 +46,33 @@ func (opt *ListIssueCommentOptions) QueryEncode() string { } // ListIssueComments list comments on an issue. -func (c *Client) ListIssueComments(owner, repo string, index int64, opt ListIssueCommentOptions) ([]*Comment, error) { +func (c *Client) ListIssueComments(owner, repo string, index int64, opt ListIssueCommentOptions) ([]*Comment, *Response, error) { opt.setDefaults() link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/%d/comments", owner, repo, index)) link.RawQuery = opt.QueryEncode() comments := make([]*Comment, 0, opt.PageSize) - return comments, c.getParsedResponse("GET", link.String(), nil, nil, &comments) + resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &comments) + return comments, resp, err } // ListRepoIssueComments list comments for a given repo. -func (c *Client) ListRepoIssueComments(owner, repo string, opt ListIssueCommentOptions) ([]*Comment, error) { +func (c *Client) ListRepoIssueComments(owner, repo string, opt ListIssueCommentOptions) ([]*Comment, *Response, error) { opt.setDefaults() link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/comments", owner, repo)) link.RawQuery = opt.QueryEncode() comments := make([]*Comment, 0, opt.PageSize) - return comments, c.getParsedResponse("GET", link.String(), nil, nil, &comments) + resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &comments) + return comments, resp, err } // GetIssueComment get a comment for a given repo by id. -func (c *Client) GetIssueComment(owner, repo string, id int64) (*Comment, error) { +func (c *Client) GetIssueComment(owner, repo string, id int64) (*Comment, *Response, error) { comment := new(Comment) - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return comment, err + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return comment, nil, err } - return comment, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, id), nil, nil, &comment) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, id), nil, nil, &comment) + return comment, resp, err } // CreateIssueCommentOption options for creating a comment on an issue @@ -77,14 +80,26 @@ type CreateIssueCommentOption struct { Body string `json:"body"` } +// Validate the CreateIssueCommentOption struct +func (opt CreateIssueCommentOption) Validate() error { + if len(opt.Body) == 0 { + return fmt.Errorf("body is empty") + } + return nil +} + // CreateIssueComment create comment on an issue. -func (c *Client) CreateIssueComment(owner, repo string, index int64, opt CreateIssueCommentOption) (*Comment, error) { +func (c *Client) CreateIssueComment(owner, repo string, index int64, opt CreateIssueCommentOption) (*Comment, *Response, error) { + if err := opt.Validate(); err != nil { + return nil, nil, err + } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } comment := new(Comment) - return comment, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/comments", owner, repo, index), jsonHeader, bytes.NewReader(body), comment) + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/comments", owner, repo, index), jsonHeader, bytes.NewReader(body), comment) + return comment, resp, err } // EditIssueCommentOption options for editing a comment @@ -92,18 +107,30 @@ type EditIssueCommentOption struct { Body string `json:"body"` } +// Validate the EditIssueCommentOption struct +func (opt EditIssueCommentOption) Validate() error { + if len(opt.Body) == 0 { + return fmt.Errorf("body is empty") + } + return nil +} + // EditIssueComment edits an issue comment. -func (c *Client) EditIssueComment(owner, repo string, commentID int64, opt EditIssueCommentOption) (*Comment, error) { +func (c *Client) EditIssueComment(owner, repo string, commentID int64, opt EditIssueCommentOption) (*Comment, *Response, error) { + if err := opt.Validate(); err != nil { + return nil, nil, err + } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } comment := new(Comment) - return comment, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, commentID), jsonHeader, bytes.NewReader(body), comment) + resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, commentID), jsonHeader, bytes.NewReader(body), comment) + return comment, resp, err } // DeleteIssueComment deletes an issue comment. -func (c *Client) DeleteIssueComment(owner, repo string, commentID int64) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, commentID), nil, nil) - return err +func (c *Client) DeleteIssueComment(owner, repo string, commentID int64) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, commentID), nil, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/issue_label.go b/vendor/code.gitea.io/sdk/gitea/issue_label.go index c5e560ab0..b664dacd1 100644 --- a/vendor/code.gitea.io/sdk/gitea/issue_label.go +++ b/vendor/code.gitea.io/sdk/gitea/issue_label.go @@ -8,6 +8,8 @@ import ( "bytes" "encoding/json" "fmt" + "regexp" + "strings" ) // Label a label to an issue or a pr @@ -26,17 +28,18 @@ type ListLabelsOptions struct { } // ListRepoLabels list labels of one repository -func (c *Client) ListRepoLabels(owner, repo string, opt ListLabelsOptions) ([]*Label, error) { +func (c *Client) ListRepoLabels(owner, repo string, opt ListLabelsOptions) ([]*Label, *Response, error) { opt.setDefaults() labels := make([]*Label, 0, opt.PageSize) - return labels, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels?%s", owner, repo, opt.getURLQuery().Encode()), nil, nil, &labels) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels?%s", owner, repo, opt.getURLQuery().Encode()), nil, nil, &labels) + return labels, resp, err } // GetRepoLabel get one label of repository by repo it -// TODO: maybe we need get a label by name -func (c *Client) GetRepoLabel(owner, repo string, id int64) (*Label, error) { +func (c *Client) GetRepoLabel(owner, repo string, id int64) (*Label, *Response, error) { label := new(Label) - return label, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil, label) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil, label) + return label, resp, err } // CreateLabelOption options for creating a label @@ -47,20 +50,40 @@ type CreateLabelOption struct { Description string `json:"description"` } +// Validate the CreateLabelOption struct +func (opt CreateLabelOption) Validate() error { + aw, err := regexp.MatchString("^#?[0-9,a-f,A-F]{6}$", opt.Color) + if err != nil { + return err + } + if !aw { + return fmt.Errorf("invalid color format") + } + if len(strings.TrimSpace(opt.Name)) == 0 { + return fmt.Errorf("empty name not allowed") + } + return nil +} + // CreateLabel create one label of repository -func (c *Client) CreateLabel(owner, repo string, opt CreateLabelOption) (*Label, error) { +func (c *Client) CreateLabel(owner, repo string, opt CreateLabelOption) (*Label, *Response, error) { + if err := opt.Validate(); err != nil { + return nil, nil, err + } if len(opt.Color) == 6 { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { opt.Color = "#" + opt.Color } } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } label := new(Label) - return label, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/labels", owner, repo), + resp, err := c.getParsedResponse("POST", + fmt.Sprintf("/repos/%s/%s/labels", owner, repo), jsonHeader, bytes.NewReader(body), label) + return label, resp, err } // EditLabelOption options for editing a label @@ -70,27 +93,50 @@ type EditLabelOption struct { Description *string `json:"description"` } +// Validate the EditLabelOption struct +func (opt EditLabelOption) Validate() error { + if opt.Color != nil { + aw, err := regexp.MatchString("^#?[0-9,a-f,A-F]{6}$", *opt.Color) + if err != nil { + return err + } + if !aw { + return fmt.Errorf("invalid color format") + } + } + if opt.Name != nil { + if len(strings.TrimSpace(*opt.Name)) == 0 { + return fmt.Errorf("empty name not allowed") + } + } + return nil +} + // EditLabel modify one label with options -func (c *Client) EditLabel(owner, repo string, id int64, opt EditLabelOption) (*Label, error) { +func (c *Client) EditLabel(owner, repo string, id int64, opt EditLabelOption) (*Label, *Response, error) { + if err := opt.Validate(); err != nil { + return nil, nil, err + } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } label := new(Label) - return label, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), jsonHeader, bytes.NewReader(body), label) + resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), jsonHeader, bytes.NewReader(body), label) + return label, resp, err } // DeleteLabel delete one label of repository by id -// TODO: maybe we need delete by name -func (c *Client) DeleteLabel(owner, repo string, id int64) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil) - return err +func (c *Client) DeleteLabel(owner, repo string, id int64) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil) + return resp, err } // GetIssueLabels get labels of one issue via issue id -func (c *Client) GetIssueLabels(owner, repo string, index int64, opts ListLabelsOptions) ([]*Label, error) { +func (c *Client) GetIssueLabels(owner, repo string, index int64, opts ListLabelsOptions) ([]*Label, *Response, error) { labels := make([]*Label, 0, 5) - return labels, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/labels?%s", owner, repo, index, opts.getURLQuery().Encode()), nil, nil, &labels) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/labels?%s", owner, repo, index, opts.getURLQuery().Encode()), nil, nil, &labels) + return labels, resp, err } // IssueLabelsOption a collection of labels @@ -100,34 +146,36 @@ type IssueLabelsOption struct { } // AddIssueLabels add one or more labels to one issue -func (c *Client) AddIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, error) { +func (c *Client) AddIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, *Response, error) { body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } var labels []*Label - return labels, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), jsonHeader, bytes.NewReader(body), &labels) + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), jsonHeader, bytes.NewReader(body), &labels) + return labels, resp, err } // ReplaceIssueLabels replace old labels of issue with new labels -func (c *Client) ReplaceIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, error) { +func (c *Client) ReplaceIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, *Response, error) { body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } var labels []*Label - return labels, c.getParsedResponse("PUT", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), jsonHeader, bytes.NewReader(body), &labels) + resp, err := c.getParsedResponse("PUT", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), jsonHeader, bytes.NewReader(body), &labels) + return labels, resp, err } // DeleteIssueLabel delete one label of one issue by issue id and label id // TODO: maybe we need delete by label name and issue id -func (c *Client) DeleteIssueLabel(owner, repo string, index, label int64) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels/%d", owner, repo, index, label), nil, nil) - return err +func (c *Client) DeleteIssueLabel(owner, repo string, index, label int64) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels/%d", owner, repo, index, label), nil, nil) + return resp, err } // ClearIssueLabels delete all the labels of one issue. -func (c *Client) ClearIssueLabels(owner, repo string, index int64) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), nil, nil) - return err +func (c *Client) ClearIssueLabels(owner, repo string, index int64) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), nil, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/issue_milestone.go b/vendor/code.gitea.io/sdk/gitea/issue_milestone.go index 41fca1fd5..236c2367b 100644 --- a/vendor/code.gitea.io/sdk/gitea/issue_milestone.go +++ b/vendor/code.gitea.io/sdk/gitea/issue_milestone.go @@ -9,6 +9,7 @@ import ( "encoding/json" "fmt" "net/url" + "strings" "time" ) @@ -20,6 +21,8 @@ type Milestone struct { State StateType `json:"state"` OpenIssues int `json:"open_issues"` ClosedIssues int `json:"closed_issues"` + Created time.Time `json:"created_at"` + Updated *time.Time `json:"updated_at"` Closed *time.Time `json:"closed_at"` Deadline *time.Time `json:"due_on"` } @@ -29,6 +32,7 @@ type ListMilestoneOption struct { ListOptions // open, closed, all State StateType + Name string } // QueryEncode turns options into querystring argument @@ -37,23 +41,40 @@ func (opt *ListMilestoneOption) QueryEncode() string { if opt.State != "" { query.Add("state", string(opt.State)) } + if len(opt.Name) != 0 { + query.Add("name", opt.Name) + } return query.Encode() } // ListRepoMilestones list all the milestones of one repository -func (c *Client) ListRepoMilestones(owner, repo string, opt ListMilestoneOption) ([]*Milestone, error) { +func (c *Client) ListRepoMilestones(owner, repo string, opt ListMilestoneOption) ([]*Milestone, *Response, error) { opt.setDefaults() milestones := make([]*Milestone, 0, opt.PageSize) link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/milestones", owner, repo)) link.RawQuery = opt.QueryEncode() - return milestones, c.getParsedResponse("GET", link.String(), nil, nil, &milestones) + resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &milestones) + return milestones, resp, err } // GetMilestone get one milestone by repo name and milestone id -func (c *Client) GetMilestone(owner, repo string, id int64) (*Milestone, error) { +func (c *Client) GetMilestone(owner, repo string, id int64) (*Milestone, *Response, error) { milestone := new(Milestone) - return milestone, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil, milestone) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil, milestone) + return milestone, resp, err +} + +// GetMilestoneByName get one milestone by repo and milestone name +func (c *Client) GetMilestoneByName(owner, repo string, name string) (*Milestone, *Response, error) { + if c.CheckServerVersionConstraint(">=1.13") != nil { + // backwards compatibility mode + m, resp, err := c.resolveMilestoneByName(owner, repo, name) + return m, resp, err + } + milestone := new(Milestone) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones/%s", owner, repo, name), nil, nil, milestone) + return milestone, resp, err } // CreateMilestoneOption options for creating a milestone @@ -64,47 +85,129 @@ type CreateMilestoneOption struct { Deadline *time.Time `json:"due_on"` } +// Validate the CreateMilestoneOption struct +func (opt CreateMilestoneOption) Validate() error { + if len(strings.TrimSpace(opt.Title)) == 0 { + return fmt.Errorf("title is empty") + } + return nil +} + // CreateMilestone create one milestone with options -func (c *Client) CreateMilestone(owner, repo string, opt CreateMilestoneOption) (*Milestone, error) { +func (c *Client) CreateMilestone(owner, repo string, opt CreateMilestoneOption) (*Milestone, *Response, error) { + if err := opt.Validate(); err != nil { + return nil, nil, err + } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } milestone := new(Milestone) - err = c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/milestones", owner, repo), jsonHeader, bytes.NewReader(body), milestone) + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/milestones", owner, repo), jsonHeader, bytes.NewReader(body), milestone) // make creating closed milestones need gitea >= v1.13.0 // this make it backwards compatible if err == nil && opt.State == StateClosed && milestone.State != StateClosed { - closed := "closed" + closed := StateClosed return c.EditMilestone(owner, repo, milestone.ID, EditMilestoneOption{ State: &closed, }) } - return milestone, err + return milestone, resp, err } // EditMilestoneOption options for editing a milestone type EditMilestoneOption struct { Title string `json:"title"` Description *string `json:"description"` - State *string `json:"state"` + State *StateType `json:"state"` Deadline *time.Time `json:"due_on"` } +// Validate the EditMilestoneOption struct +func (opt EditMilestoneOption) Validate() error { + if len(opt.Title) != 0 && len(strings.TrimSpace(opt.Title)) == 0 { + return fmt.Errorf("title is empty") + } + return nil +} + // EditMilestone modify milestone with options -func (c *Client) EditMilestone(owner, repo string, id int64, opt EditMilestoneOption) (*Milestone, error) { +func (c *Client) EditMilestone(owner, repo string, id int64, opt EditMilestoneOption) (*Milestone, *Response, error) { + if err := opt.Validate(); err != nil { + return nil, nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, nil, err + } + milestone := new(Milestone) + resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), jsonHeader, bytes.NewReader(body), milestone) + return milestone, resp, err +} + +// EditMilestoneByName modify milestone with options +func (c *Client) EditMilestoneByName(owner, repo string, name string, opt EditMilestoneOption) (*Milestone, *Response, error) { + if c.CheckServerVersionConstraint(">=1.13") != nil { + // backwards compatibility mode + m, _, err := c.resolveMilestoneByName(owner, repo, name) + if err != nil { + return nil, nil, err + } + return c.EditMilestone(owner, repo, m.ID, opt) + } + if err := opt.Validate(); err != nil { + return nil, nil, err + } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } milestone := new(Milestone) - return milestone, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), jsonHeader, bytes.NewReader(body), milestone) + resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/milestones/%s", owner, repo, name), jsonHeader, bytes.NewReader(body), milestone) + return milestone, resp, err } -// DeleteMilestone delete one milestone by milestone id -func (c *Client) DeleteMilestone(owner, repo string, id int64) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil) - return err +// DeleteMilestone delete one milestone by id +func (c *Client) DeleteMilestone(owner, repo string, id int64) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil) + return resp, err +} + +// DeleteMilestoneByName delete one milestone by name +func (c *Client) DeleteMilestoneByName(owner, repo string, name string) (*Response, error) { + if c.CheckServerVersionConstraint(">=1.13") != nil { + // backwards compatibility mode + m, _, err := c.resolveMilestoneByName(owner, repo, name) + if err != nil { + return nil, err + } + return c.DeleteMilestone(owner, repo, m.ID) + } + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/milestones/%s", owner, repo, name), nil, nil) + return resp, err +} + +// resolveMilestoneByName is a fallback method to find milestone id by name +func (c *Client) resolveMilestoneByName(owner, repo, name string) (*Milestone, *Response, error) { + for i := 1; ; i++ { + miles, resp, err := c.ListRepoMilestones(owner, repo, ListMilestoneOption{ + ListOptions: ListOptions{ + Page: i, + }, + State: "all", + }) + if err != nil { + return nil, nil, err + } + if len(miles) == 0 { + return nil, nil, fmt.Errorf("milestone '%s' do not exist", name) + } + for _, m := range miles { + if strings.ToLower(strings.TrimSpace(m.Title)) == strings.ToLower(strings.TrimSpace(name)) { + return m, resp, nil + } + } + } } diff --git a/vendor/code.gitea.io/sdk/gitea/issue_reaction.go b/vendor/code.gitea.io/sdk/gitea/issue_reaction.go index fb7d6d6cf..efdac08aa 100644 --- a/vendor/code.gitea.io/sdk/gitea/issue_reaction.go +++ b/vendor/code.gitea.io/sdk/gitea/issue_reaction.go @@ -19,21 +19,17 @@ type Reaction struct { } // GetIssueReactions get a list reactions of an issue -func (c *Client) GetIssueReactions(owner, repo string, index int64) ([]*Reaction, error) { - if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil { - return nil, err - } +func (c *Client) GetIssueReactions(owner, repo string, index int64) ([]*Reaction, *Response, error) { reactions := make([]*Reaction, 0, 10) - return reactions, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index), nil, nil, &reactions) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index), nil, nil, &reactions) + return reactions, resp, err } // GetIssueCommentReactions get a list of reactions from a comment of an issue -func (c *Client) GetIssueCommentReactions(owner, repo string, commentID int64) ([]*Reaction, error) { - if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil { - return nil, err - } +func (c *Client) GetIssueCommentReactions(owner, repo string, commentID int64) ([]*Reaction, *Response, error) { reactions := make([]*Reaction, 0, 10) - return reactions, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/comments/%d/reactions", owner, repo, commentID), nil, nil, &reactions) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/comments/%d/reactions", owner, repo, commentID), nil, nil, &reactions) + return reactions, resp, err } // editReactionOption contain the reaction type @@ -42,57 +38,49 @@ type editReactionOption struct { } // PostIssueReaction add a reaction to an issue -func (c *Client) PostIssueReaction(owner, repo string, index int64, reaction string) (*Reaction, error) { - if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil { - return nil, err - } +func (c *Client) PostIssueReaction(owner, repo string, index int64, reaction string) (*Reaction, *Response, error) { reactionResponse := new(Reaction) body, err := json.Marshal(&editReactionOption{Reaction: reaction}) if err != nil { - return nil, err + return nil, nil, err } - return reactionResponse, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index), + resp, err := c.getParsedResponse("POST", + fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index), jsonHeader, bytes.NewReader(body), reactionResponse) + return reactionResponse, resp, err } // DeleteIssueReaction remove a reaction from an issue -func (c *Client) DeleteIssueReaction(owner, repo string, index int64, reaction string) error { - if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil { - return err - } +func (c *Client) DeleteIssueReaction(owner, repo string, index int64, reaction string) (*Response, error) { body, err := json.Marshal(&editReactionOption{Reaction: reaction}) if err != nil { - return err + return nil, err } - _, err = c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index), jsonHeader, bytes.NewReader(body)) - return err + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index), jsonHeader, bytes.NewReader(body)) + return resp, err } // PostIssueCommentReaction add a reaction to a comment of an issue -func (c *Client) PostIssueCommentReaction(owner, repo string, commentID int64, reaction string) (*Reaction, error) { - if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil { - return nil, err - } +func (c *Client) PostIssueCommentReaction(owner, repo string, commentID int64, reaction string) (*Reaction, *Response, error) { reactionResponse := new(Reaction) body, err := json.Marshal(&editReactionOption{Reaction: reaction}) if err != nil { - return nil, err + return nil, nil, err } - return reactionResponse, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/comments/%d/reactions", owner, repo, commentID), + resp, err := c.getParsedResponse("POST", + fmt.Sprintf("/repos/%s/%s/issues/comments/%d/reactions", owner, repo, commentID), jsonHeader, bytes.NewReader(body), reactionResponse) + return reactionResponse, resp, err } // DeleteIssueCommentReaction remove a reaction from a comment of an issue -func (c *Client) DeleteIssueCommentReaction(owner, repo string, commentID int64, reaction string) error { - if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil { - return err - } - // swagger:operation DELETE /repos/{owner}/{repo}/issues/comments/{id}/reactions issue issueDeleteCommentReaction +func (c *Client) DeleteIssueCommentReaction(owner, repo string, commentID int64, reaction string) (*Response, error) { body, err := json.Marshal(&editReactionOption{Reaction: reaction}) if err != nil { - return err + return nil, err } - _, err = c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/comments/%d/reactions", owner, repo, commentID), + _, resp, err := c.getResponse("DELETE", + fmt.Sprintf("/repos/%s/%s/issues/comments/%d/reactions", owner, repo, commentID), jsonHeader, bytes.NewReader(body)) - return err + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/issue_stopwatch.go b/vendor/code.gitea.io/sdk/gitea/issue_stopwatch.go index 8b8f178de..35e1efe3f 100644 --- a/vendor/code.gitea.io/sdk/gitea/issue_stopwatch.go +++ b/vendor/code.gitea.io/sdk/gitea/issue_stopwatch.go @@ -11,32 +11,38 @@ import ( // StopWatch represents a running stopwatch of an issue / pr type StopWatch struct { - Created time.Time `json:"created"` - IssueIndex int64 `json:"issue_index"` + Created time.Time `json:"created"` + Seconds int64 `json:"seconds"` + Duration string `json:"duration"` + IssueIndex int64 `json:"issue_index"` + IssueTitle string `json:"issue_title"` + RepoOwnerName string `json:"repo_owner_name"` + RepoName string `json:"repo_name"` } // GetMyStopwatches list all stopwatches -func (c *Client) GetMyStopwatches() ([]*StopWatch, error) { +func (c *Client) GetMyStopwatches() ([]*StopWatch, *Response, error) { stopwatches := make([]*StopWatch, 0, 1) - return stopwatches, c.getParsedResponse("GET", "/user/stopwatches", nil, nil, &stopwatches) + resp, err := c.getParsedResponse("GET", "/user/stopwatches", nil, nil, &stopwatches) + return stopwatches, resp, err } // DeleteIssueStopwatch delete / cancel a specific stopwatch -func (c *Client) DeleteIssueStopwatch(owner, repo string, index int64) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/delete", owner, repo, index), nil, nil) - return err +func (c *Client) DeleteIssueStopwatch(owner, repo string, index int64) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/delete", owner, repo, index), nil, nil) + return resp, err } // StartIssueStopWatch starts a stopwatch for an existing issue for a given // repository -func (c *Client) StartIssueStopWatch(owner, repo string, index int64) error { - _, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/start", owner, repo, index), nil, nil) - return err +func (c *Client) StartIssueStopWatch(owner, repo string, index int64) (*Response, error) { + _, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/start", owner, repo, index), nil, nil) + return resp, err } // StopIssueStopWatch stops an existing stopwatch for an issue in a given // repository -func (c *Client) StopIssueStopWatch(owner, repo string, index int64) error { - _, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/stop", owner, repo, index), nil, nil) - return err +func (c *Client) StopIssueStopWatch(owner, repo string, index int64) (*Response, error) { + _, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/stop", owner, repo, index), nil, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/issue_subscription.go b/vendor/code.gitea.io/sdk/gitea/issue_subscription.go index b7980cf9a..35972bad8 100644 --- a/vendor/code.gitea.io/sdk/gitea/issue_subscription.go +++ b/vendor/code.gitea.io/sdk/gitea/issue_subscription.go @@ -10,73 +10,66 @@ import ( ) // GetIssueSubscribers get list of users who subscribed on an issue -func (c *Client) GetIssueSubscribers(owner, repo string, index int64) ([]*User, error) { - if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil { - return nil, err - } +func (c *Client) GetIssueSubscribers(owner, repo string, index int64) ([]*User, *Response, error) { subscribers := make([]*User, 0, 10) - return subscribers, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions", owner, repo, index), nil, nil, &subscribers) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions", owner, repo, index), nil, nil, &subscribers) + return subscribers, resp, err } // AddIssueSubscription Subscribe user to issue -func (c *Client) AddIssueSubscription(owner, repo string, index int64, user string) error { - if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil { - return err - } - status, err := c.getStatusCode("PUT", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil) +func (c *Client) AddIssueSubscription(owner, repo string, index int64, user string) (*Response, error) { + status, resp, err := c.getStatusCode("PUT", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil) if err != nil { - return err + return resp, err } if status == http.StatusCreated { - return nil + return resp, nil } if status == http.StatusOK { - return fmt.Errorf("already subscribed") + return resp, fmt.Errorf("already subscribed") } - return fmt.Errorf("unexpected Status: %d", status) + return resp, fmt.Errorf("unexpected Status: %d", status) } // DeleteIssueSubscription unsubscribe user from issue -func (c *Client) DeleteIssueSubscription(owner, repo string, index int64, user string) error { - if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil { - return err - } - status, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil) +func (c *Client) DeleteIssueSubscription(owner, repo string, index int64, user string) (*Response, error) { + status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil) if err != nil { - return err + return resp, err } if status == http.StatusCreated { - return nil + return resp, nil } if status == http.StatusOK { - return fmt.Errorf("already unsubscribed") + return resp, fmt.Errorf("already unsubscribed") } - return fmt.Errorf("unexpected Status: %d", status) + return resp, fmt.Errorf("unexpected Status: %d", status) } // CheckIssueSubscription check if current user is subscribed to an issue -func (c *Client) CheckIssueSubscription(owner, repo string, index int64) (*WatchInfo, error) { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return nil, err +func (c *Client) CheckIssueSubscription(owner, repo string, index int64) (*WatchInfo, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, nil, err } wi := new(WatchInfo) - return wi, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/check", owner, repo, index), nil, nil, wi) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/check", owner, repo, index), nil, nil, wi) + return wi, resp, err } // IssueSubscribe subscribe current user to an issue -func (c *Client) IssueSubscribe(owner, repo string, index int64) error { - u, err := c.GetMyUserInfo() +func (c *Client) IssueSubscribe(owner, repo string, index int64) (*Response, error) { + u, _, err := c.GetMyUserInfo() if err != nil { - return err + return nil, err } return c.AddIssueSubscription(owner, repo, index, u.UserName) } // IssueUnSubscribe unsubscribe current user from an issue -func (c *Client) IssueUnSubscribe(owner, repo string, index int64) error { - u, err := c.GetMyUserInfo() +func (c *Client) IssueUnSubscribe(owner, repo string, index int64) (*Response, error) { + u, _, err := c.GetMyUserInfo() if err != nil { - return err + return nil, err } return c.DeleteIssueSubscription(owner, repo, index, u.UserName) } diff --git a/vendor/code.gitea.io/sdk/gitea/issue_tracked_time.go b/vendor/code.gitea.io/sdk/gitea/issue_tracked_time.go index 51f1a99b6..6a326cf08 100644 --- a/vendor/code.gitea.io/sdk/gitea/issue_tracked_time.go +++ b/vendor/code.gitea.io/sdk/gitea/issue_tracked_time.go @@ -8,6 +8,7 @@ import ( "bytes" "encoding/json" "fmt" + "net/url" "time" ) @@ -25,65 +26,102 @@ type TrackedTime struct { Issue *Issue `json:"issue"` } -// GetUserTrackedTimes list tracked times of a user -func (c *Client) GetUserTrackedTimes(owner, repo, user string) ([]*TrackedTime, error) { - times := make([]*TrackedTime, 0, 10) - return times, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/times/%s", owner, repo, user), nil, nil, ×) +// ListTrackedTimesOptions options for listing repository's tracked times +type ListTrackedTimesOptions struct { + ListOptions + Since time.Time + Before time.Time + // User filter is only used by ListRepoTrackedTimes !!! + User string } -// GetRepoTrackedTimes list tracked times of a repository -func (c *Client) GetRepoTrackedTimes(owner, repo string) ([]*TrackedTime, error) { - times := make([]*TrackedTime, 0, 10) - return times, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/times", owner, repo), nil, nil, ×) +// QueryEncode turns options into querystring argument +func (opt *ListTrackedTimesOptions) QueryEncode() string { + query := opt.getURLQuery() + + if !opt.Since.IsZero() { + query.Add("since", opt.Since.Format(time.RFC3339)) + } + if !opt.Before.IsZero() { + query.Add("before", opt.Before.Format(time.RFC3339)) + } + + if len(opt.User) != 0 { + query.Add("user", opt.User) + } + + return query.Encode() +} + +// ListRepoTrackedTimes list tracked times of a repository +func (c *Client) ListRepoTrackedTimes(owner, repo string, opt ListTrackedTimesOptions) ([]*TrackedTime, *Response, error) { + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/times", owner, repo)) + opt.setDefaults() + link.RawQuery = opt.QueryEncode() + times := make([]*TrackedTime, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, ×) + return times, resp, err } // GetMyTrackedTimes list tracked times of the current user -func (c *Client) GetMyTrackedTimes() ([]*TrackedTime, error) { +func (c *Client) GetMyTrackedTimes() ([]*TrackedTime, *Response, error) { times := make([]*TrackedTime, 0, 10) - return times, c.getParsedResponse("GET", "/user/times", nil, nil, ×) + resp, err := c.getParsedResponse("GET", "/user/times", jsonHeader, nil, ×) + return times, resp, err } // AddTimeOption options for adding time to an issue type AddTimeOption struct { // time in seconds - Time int64 `json:"time" binding:"Required"` + Time int64 `json:"time"` // optional Created time.Time `json:"created"` // optional User string `json:"user_name"` } +// Validate the AddTimeOption struct +func (opt AddTimeOption) Validate() error { + if opt.Time == 0 { + return fmt.Errorf("no time to add") + } + return nil +} + // AddTime adds time to issue with the given index -func (c *Client) AddTime(owner, repo string, index int64, opt AddTimeOption) (*TrackedTime, error) { +func (c *Client) AddTime(owner, repo string, index int64, opt AddTimeOption) (*TrackedTime, *Response, error) { + if err := opt.Validate(); err != nil { + return nil, nil, err + } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } t := new(TrackedTime) - return t, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index), + resp, err := c.getParsedResponse("POST", + fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index), jsonHeader, bytes.NewReader(body), t) + return t, resp, err } -// ListTrackedTimesOptions options for listing repository's tracked times -type ListTrackedTimesOptions struct { - ListOptions -} - -// ListTrackedTimes list tracked times of a single issue for a given repository -func (c *Client) ListTrackedTimes(owner, repo string, index int64, opt ListTrackedTimesOptions) ([]*TrackedTime, error) { +// ListIssueTrackedTimes list tracked times of a single issue for a given repository +func (c *Client) ListIssueTrackedTimes(owner, repo string, index int64, opt ListTrackedTimesOptions) ([]*TrackedTime, *Response, error) { + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index)) opt.setDefaults() + link.RawQuery = opt.QueryEncode() times := make([]*TrackedTime, 0, opt.PageSize) - return times, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/times?%s", owner, repo, index, opt.getURLQuery().Encode()), nil, nil, ×) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, ×) + return times, resp, err } // ResetIssueTime reset tracked time of a single issue for a given repository -func (c *Client) ResetIssueTime(owner, repo string, index int64) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index), nil, nil) - return err +func (c *Client) ResetIssueTime(owner, repo string, index int64) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index), jsonHeader, nil) + return resp, err } // DeleteTime delete a specific tracked time by id of a single issue for a given repository -func (c *Client) DeleteTime(owner, repo string, index, timeID int64) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times/%d", owner, repo, index, timeID), nil, nil) - return err +func (c *Client) DeleteTime(owner, repo string, index, timeID int64) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times/%d", owner, repo, index, timeID), jsonHeader, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/notifications.go b/vendor/code.gitea.io/sdk/gitea/notifications.go index 188de88c3..30b6b6d01 100644 --- a/vendor/code.gitea.io/sdk/gitea/notifications.go +++ b/vendor/code.gitea.io/sdk/gitea/notifications.go @@ -8,6 +8,12 @@ import ( "fmt" "net/url" "time" + + "github.com/hashicorp/go-version" +) + +var ( + version1_12_3, _ = version.NewVersion("1.12.3") ) // NotificationThread expose Notification on API @@ -23,22 +29,38 @@ type NotificationThread struct { // NotificationSubject contains the notification subject (Issue/Pull/Commit) type NotificationSubject struct { - Title string `json:"title"` - URL string `json:"url"` - LatestCommentURL string `json:"latest_comment_url"` - Type string `json:"type" binding:"In(Issue,Pull,Commit)"` + Title string `json:"title"` + URL string `json:"url"` + LatestCommentURL string `json:"latest_comment_url"` + Type string `json:"type"` + State StateType `json:"state"` } +// NotifyStatus notification status type +type NotifyStatus string + +const ( + // NotifyStatusUnread was not read + NotifyStatusUnread NotifyStatus = "unread" + // NotifyStatusRead was already read by user + NotifyStatusRead NotifyStatus = "read" + // NotifyStatusPinned notification is pinned by user + NotifyStatusPinned NotifyStatus = "pinned" +) + // ListNotificationOptions represents the filter options type ListNotificationOptions struct { ListOptions Since time.Time Before time.Time + Status []NotifyStatus } -// MarkNotificationOptions represents the filter options +// MarkNotificationOptions represents the filter & modify options type MarkNotificationOptions struct { LastReadAt time.Time + Status []NotifyStatus + ToStatus NotifyStatus } // QueryEncode encode options to url query @@ -50,88 +72,134 @@ func (opt *ListNotificationOptions) QueryEncode() string { if !opt.Before.IsZero() { query.Add("before", opt.Before.Format(time.RFC3339)) } + for _, s := range opt.Status { + query.Add("status-types", string(s)) + } return query.Encode() } +// Validate the CreateUserOption struct +func (opt ListNotificationOptions) Validate(c *Client) error { + if len(opt.Status) != 0 { + return c.checkServerVersionGreaterThanOrEqual(version1_12_3) + } + return nil +} + // QueryEncode encode options to url query func (opt *MarkNotificationOptions) QueryEncode() string { query := make(url.Values) if !opt.LastReadAt.IsZero() { query.Add("last_read_at", opt.LastReadAt.Format(time.RFC3339)) } + for _, s := range opt.Status { + query.Add("status-types", string(s)) + } + if len(opt.ToStatus) != 0 { + query.Add("to-status", string(opt.ToStatus)) + } return query.Encode() } +// Validate the CreateUserOption struct +func (opt MarkNotificationOptions) Validate(c *Client) error { + if len(opt.Status) != 0 || len(opt.ToStatus) != 0 { + return c.checkServerVersionGreaterThanOrEqual(version1_12_3) + } + return nil +} + // CheckNotifications list users's notification threads -func (c *Client) CheckNotifications() (int64, error) { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return 0, err +func (c *Client) CheckNotifications() (int64, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return 0, nil, err } new := struct { New int64 `json:"new"` }{} - return new.New, c.getParsedResponse("GET", "/notifications/new", jsonHeader, nil, &new) + resp, err := c.getParsedResponse("GET", "/notifications/new", jsonHeader, nil, &new) + return new.New, resp, err } // GetNotification get notification thread by ID -func (c *Client) GetNotification(id int64) (*NotificationThread, error) { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return nil, err +func (c *Client) GetNotification(id int64) (*NotificationThread, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, nil, err } thread := new(NotificationThread) - return thread, c.getParsedResponse("GET", fmt.Sprintf("/notifications/threads/%d", id), nil, nil, thread) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/notifications/threads/%d", id), nil, nil, thread) + return thread, resp, err } // ReadNotification mark notification thread as read by ID -func (c *Client) ReadNotification(id int64) error { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return err +// It optionally takes a second argument if status has to be set other than 'read' +func (c *Client) ReadNotification(id int64, status ...NotifyStatus) (*Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, err + } + link := fmt.Sprintf("/notifications/threads/%d", id) + if len(status) != 0 { + link += fmt.Sprintf("?to-status=%s", status[0]) } - _, err := c.getResponse("PATCH", fmt.Sprintf("/notifications/threads/%d", id), nil, nil) - return err + _, resp, err := c.getResponse("PATCH", link, nil, nil) + return resp, err } // ListNotifications list users's notification threads -func (c *Client) ListNotifications(opt ListNotificationOptions) ([]*NotificationThread, error) { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return nil, err +func (c *Client) ListNotifications(opt ListNotificationOptions) ([]*NotificationThread, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, nil, err + } + if err := opt.Validate(c); err != nil { + return nil, nil, err } link, _ := url.Parse("/notifications") link.RawQuery = opt.QueryEncode() threads := make([]*NotificationThread, 0, 10) - return threads, c.getParsedResponse("GET", link.String(), nil, nil, &threads) + resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &threads) + return threads, resp, err } // ReadNotifications mark notification threads as read -func (c *Client) ReadNotifications(opt MarkNotificationOptions) error { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return err +func (c *Client) ReadNotifications(opt MarkNotificationOptions) (*Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, err + } + if err := opt.Validate(c); err != nil { + return nil, err } link, _ := url.Parse("/notifications") link.RawQuery = opt.QueryEncode() - _, err := c.getResponse("PUT", link.String(), nil, nil) - return err + _, resp, err := c.getResponse("PUT", link.String(), nil, nil) + return resp, err } // ListRepoNotifications list users's notification threads on a specific repo -func (c *Client) ListRepoNotifications(owner, reponame string, opt ListNotificationOptions) ([]*NotificationThread, error) { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return nil, err +func (c *Client) ListRepoNotifications(owner, reponame string, opt ListNotificationOptions) ([]*NotificationThread, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, nil, err + } + if err := opt.Validate(c); err != nil { + return nil, nil, err } link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/notifications", owner, reponame)) link.RawQuery = opt.QueryEncode() threads := make([]*NotificationThread, 0, 10) - return threads, c.getParsedResponse("GET", link.String(), nil, nil, &threads) + resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &threads) + return threads, resp, err } // ReadRepoNotifications mark notification threads as read on a specific repo -func (c *Client) ReadRepoNotifications(owner, reponame string, opt MarkNotificationOptions) error { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return err +func (c *Client) ReadRepoNotifications(owner, reponame string, opt MarkNotificationOptions) (*Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, err + } + if err := opt.Validate(c); err != nil { + return nil, err } link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/notifications", owner, reponame)) link.RawQuery = opt.QueryEncode() - _, err := c.getResponse("PUT", link.String(), nil, nil) - return err + _, resp, err := c.getResponse("PUT", link.String(), nil, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/oauth2.go b/vendor/code.gitea.io/sdk/gitea/oauth2.go index 527535d04..bbdfdafb6 100644 --- a/vendor/code.gitea.io/sdk/gitea/oauth2.go +++ b/vendor/code.gitea.io/sdk/gitea/oauth2.go @@ -33,55 +33,59 @@ type CreateOauth2Option struct { } // CreateOauth2 create an Oauth2 Application and returns a completed Oauth2 object. -func (c *Client) CreateOauth2(opt CreateOauth2Option) (*Oauth2, error) { - if e := c.CheckServerVersionConstraint(">=1.12.0"); e != nil { - return nil, e +func (c *Client) CreateOauth2(opt CreateOauth2Option) (*Oauth2, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, nil, err } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } oauth := new(Oauth2) - return oauth, c.getParsedResponse("POST", "/user/applications/oauth2", jsonHeader, bytes.NewReader(body), oauth) + resp, err := c.getParsedResponse("POST", "/user/applications/oauth2", jsonHeader, bytes.NewReader(body), oauth) + return oauth, resp, err } // UpdateOauth2 a specific Oauth2 Application by ID and return a completed Oauth2 object. -func (c *Client) UpdateOauth2(oauth2id int64, opt CreateOauth2Option) (*Oauth2, error) { - if e := c.CheckServerVersionConstraint(">=1.12.0"); e != nil { - return nil, e +func (c *Client) UpdateOauth2(oauth2id int64, opt CreateOauth2Option) (*Oauth2, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, nil, err } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } oauth := new(Oauth2) - return oauth, c.getParsedResponse("PATCH", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), jsonHeader, bytes.NewReader(body), oauth) + resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), jsonHeader, bytes.NewReader(body), oauth) + return oauth, resp, err } // GetOauth2 a specific Oauth2 Application by ID. -func (c *Client) GetOauth2(oauth2id int64) (*Oauth2, error) { - if e := c.CheckServerVersionConstraint(">=1.12.0"); e != nil { - return nil, e +func (c *Client) GetOauth2(oauth2id int64) (*Oauth2, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, nil, err } oauth2s := &Oauth2{} - return oauth2s, c.getParsedResponse("GET", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), nil, nil, &oauth2s) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), nil, nil, &oauth2s) + return oauth2s, resp, err } // ListOauth2 all of your Oauth2 Applications. -func (c *Client) ListOauth2(opt ListOauth2Option) ([]*Oauth2, error) { - if e := c.CheckServerVersionConstraint(">=1.12.0"); e != nil { - return nil, e +func (c *Client) ListOauth2(opt ListOauth2Option) ([]*Oauth2, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, nil, err } opt.setDefaults() oauth2s := make([]*Oauth2, 0, opt.PageSize) - return oauth2s, c.getParsedResponse("GET", fmt.Sprintf("/user/applications/oauth2?%s", opt.getURLQuery().Encode()), nil, nil, &oauth2s) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/applications/oauth2?%s", opt.getURLQuery().Encode()), nil, nil, &oauth2s) + return oauth2s, resp, err } // DeleteOauth2 delete an Oauth2 application by ID -func (c *Client) DeleteOauth2(oauth2id int64) error { - if e := c.CheckServerVersionConstraint(">=1.12.0"); e != nil { - return e +func (c *Client) DeleteOauth2(oauth2id int64) (*Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, err } - _, err := c.getResponse("DELETE", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), nil, nil) - return err + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), nil, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/org.go b/vendor/code.gitea.io/sdk/gitea/org.go index 61ade3095..ed6c678e6 100644 --- a/vendor/code.gitea.io/sdk/gitea/org.go +++ b/vendor/code.gitea.io/sdk/gitea/org.go @@ -23,76 +23,120 @@ type Organization struct { Visibility string `json:"visibility"` } +// VisibleType defines the visibility +type VisibleType string + +const ( + // VisibleTypePublic Visible for everyone + VisibleTypePublic VisibleType = "public" + + // VisibleTypeLimited Visible for every connected user + VisibleTypeLimited VisibleType = "limited" + + // VisibleTypePrivate Visible only for organization's members + VisibleTypePrivate VisibleType = "private" +) + // ListOrgsOptions options for listing organizations type ListOrgsOptions struct { ListOptions } // ListMyOrgs list all of current user's organizations -func (c *Client) ListMyOrgs(opt ListOrgsOptions) ([]*Organization, error) { +func (c *Client) ListMyOrgs(opt ListOrgsOptions) ([]*Organization, *Response, error) { opt.setDefaults() orgs := make([]*Organization, 0, opt.PageSize) - return orgs, c.getParsedResponse("GET", fmt.Sprintf("/user/orgs?%s", opt.getURLQuery().Encode()), nil, nil, &orgs) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/orgs?%s", opt.getURLQuery().Encode()), nil, nil, &orgs) + return orgs, resp, err } // ListUserOrgs list all of some user's organizations -func (c *Client) ListUserOrgs(user string, opt ListOrgsOptions) ([]*Organization, error) { +func (c *Client) ListUserOrgs(user string, opt ListOrgsOptions) ([]*Organization, *Response, error) { opt.setDefaults() orgs := make([]*Organization, 0, opt.PageSize) - return orgs, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/orgs?%s", user, opt.getURLQuery().Encode()), nil, nil, &orgs) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/orgs?%s", user, opt.getURLQuery().Encode()), nil, nil, &orgs) + return orgs, resp, err } // GetOrg get one organization by name -func (c *Client) GetOrg(orgname string) (*Organization, error) { +func (c *Client) GetOrg(orgname string) (*Organization, *Response, error) { org := new(Organization) - return org, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s", orgname), nil, nil, org) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s", orgname), nil, nil, org) + return org, resp, err } // CreateOrgOption options for creating an organization type CreateOrgOption struct { - UserName string `json:"username"` - FullName string `json:"full_name"` - Description string `json:"description"` - Website string `json:"website"` - Location string `json:"location"` - // possible values are `public` (default), `limited` or `private` - // enum: public,limited,private - Visibility string `json:"visibility"` + Name string `json:"username"` + FullName string `json:"full_name"` + Description string `json:"description"` + Website string `json:"website"` + Location string `json:"location"` + Visibility VisibleType `json:"visibility"` +} + +// checkVisibilityOpt check if mode exist +func checkVisibilityOpt(v VisibleType) bool { + return v == VisibleTypePublic || v == VisibleTypeLimited || v == VisibleTypePrivate +} + +// Validate the CreateOrgOption struct +func (opt CreateOrgOption) Validate() error { + if len(opt.Name) == 0 { + return fmt.Errorf("empty org name") + } + if len(opt.Visibility) != 0 && !checkVisibilityOpt(opt.Visibility) { + return fmt.Errorf("infalid bisibility option") + } + return nil } // CreateOrg creates an organization -func (c *Client) CreateOrg(opt CreateOrgOption) (*Organization, error) { +func (c *Client) CreateOrg(opt CreateOrgOption) (*Organization, *Response, error) { + if err := opt.Validate(); err != nil { + return nil, nil, err + } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } org := new(Organization) - return org, c.getParsedResponse("POST", "/orgs", jsonHeader, bytes.NewReader(body), org) + resp, err := c.getParsedResponse("POST", "/orgs", jsonHeader, bytes.NewReader(body), org) + return org, resp, err } // EditOrgOption options for editing an organization type EditOrgOption struct { - FullName string `json:"full_name"` - Description string `json:"description"` - Website string `json:"website"` - Location string `json:"location"` - // possible values are `public`, `limited` or `private` - // enum: public,limited,private - Visibility string `json:"visibility"` + FullName string `json:"full_name"` + Description string `json:"description"` + Website string `json:"website"` + Location string `json:"location"` + Visibility VisibleType `json:"visibility"` +} + +// Validate the EditOrgOption struct +func (opt EditOrgOption) Validate() error { + if len(opt.Visibility) != 0 && !checkVisibilityOpt(opt.Visibility) { + return fmt.Errorf("infalid bisibility option") + } + return nil } // EditOrg modify one organization via options -func (c *Client) EditOrg(orgname string, opt EditOrgOption) error { +func (c *Client) EditOrg(orgname string, opt EditOrgOption) (*Response, error) { + if err := opt.Validate(); err != nil { + return nil, err + } body, err := json.Marshal(&opt) if err != nil { - return err + return nil, err } - _, err = c.getResponse("PATCH", fmt.Sprintf("/orgs/%s", orgname), jsonHeader, bytes.NewReader(body)) - return err + _, resp, err := c.getResponse("PATCH", fmt.Sprintf("/orgs/%s", orgname), jsonHeader, bytes.NewReader(body)) + return resp, err } // DeleteOrg deletes an organization -func (c *Client) DeleteOrg(orgname string) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s", orgname), nil, nil) - return err +func (c *Client) DeleteOrg(orgname string) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s", orgname), jsonHeader, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/org_member.go b/vendor/code.gitea.io/sdk/gitea/org_member.go index 9e1bf7768..0f5b54296 100644 --- a/vendor/code.gitea.io/sdk/gitea/org_member.go +++ b/vendor/code.gitea.io/sdk/gitea/org_member.go @@ -11,9 +11,9 @@ import ( ) // DeleteOrgMembership remove a member from an organization -func (c *Client) DeleteOrgMembership(org, user string) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil) - return err +func (c *Client) DeleteOrgMembership(org, user string) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil) + return resp, err } // ListOrgMembershipOption list OrgMembership options @@ -22,77 +22,80 @@ type ListOrgMembershipOption struct { } // ListOrgMembership list an organization's members -func (c *Client) ListOrgMembership(org string, opt ListOrgMembershipOption) ([]*User, error) { +func (c *Client) ListOrgMembership(org string, opt ListOrgMembershipOption) ([]*User, *Response, error) { opt.setDefaults() users := make([]*User, 0, opt.PageSize) link, _ := url.Parse(fmt.Sprintf("/orgs/%s/members", url.PathEscape(org))) link.RawQuery = opt.getURLQuery().Encode() - return users, c.getParsedResponse("GET", link.String(), jsonHeader, nil, &users) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &users) + return users, resp, err } // ListPublicOrgMembership list an organization's members -func (c *Client) ListPublicOrgMembership(org string, opt ListOrgMembershipOption) ([]*User, error) { +func (c *Client) ListPublicOrgMembership(org string, opt ListOrgMembershipOption) ([]*User, *Response, error) { opt.setDefaults() users := make([]*User, 0, opt.PageSize) link, _ := url.Parse(fmt.Sprintf("/orgs/%s/public_members", url.PathEscape(org))) link.RawQuery = opt.getURLQuery().Encode() - return users, c.getParsedResponse("GET", link.String(), jsonHeader, nil, &users) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &users) + return users, resp, err } // CheckOrgMembership Check if a user is a member of an organization -func (c *Client) CheckOrgMembership(org, user string) (bool, error) { - status, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil) +func (c *Client) CheckOrgMembership(org, user string) (bool, *Response, error) { + status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil) if err != nil { - return false, err + return false, resp, err } switch status { case http.StatusNoContent: - return true, nil + return true, resp, nil case http.StatusNotFound: - return false, nil + return false, resp, nil default: - return false, fmt.Errorf("unexpected Status: %d", status) + return false, resp, fmt.Errorf("unexpected Status: %d", status) } } // CheckPublicOrgMembership Check if a user is a member of an organization -func (c *Client) CheckPublicOrgMembership(org, user string) (bool, error) { - status, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/public_members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil) +func (c *Client) CheckPublicOrgMembership(org, user string) (bool, *Response, error) { + status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/public_members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil) if err != nil { - return false, err + return false, resp, err } switch status { case http.StatusNoContent: - return true, nil + return true, resp, nil case http.StatusNotFound: - return false, nil + return false, resp, nil default: - return false, fmt.Errorf("unexpected Status: %d", status) + return false, resp, fmt.Errorf("unexpected Status: %d", status) } } // SetPublicOrgMembership publicize/conceal a user's membership -func (c *Client) SetPublicOrgMembership(org, user string, visible bool) error { +func (c *Client) SetPublicOrgMembership(org, user string, visible bool) (*Response, error) { var ( status int err error + resp *Response ) if visible { - status, err = c.getStatusCode("PUT", fmt.Sprintf("/orgs/%s/public_members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil) + status, resp, err = c.getStatusCode("PUT", fmt.Sprintf("/orgs/%s/public_members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil) } else { - status, err = c.getStatusCode("DELETE", fmt.Sprintf("/orgs/%s/public_members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil) + status, resp, err = c.getStatusCode("DELETE", fmt.Sprintf("/orgs/%s/public_members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil) } if err != nil { - return err + return resp, err } switch status { case http.StatusNoContent: - return nil + return resp, nil case http.StatusNotFound: - return fmt.Errorf("forbidden") + return resp, fmt.Errorf("forbidden") default: - return fmt.Errorf("unexpected Status: %d", status) + return resp, fmt.Errorf("unexpected Status: %d", status) } } diff --git a/vendor/code.gitea.io/sdk/gitea/org_team.go b/vendor/code.gitea.io/sdk/gitea/org_team.go index 4c786e3b8..148d2c2c3 100644 --- a/vendor/code.gitea.io/sdk/gitea/org_team.go +++ b/vendor/code.gitea.io/sdk/gitea/org_team.go @@ -12,12 +12,13 @@ import ( // Team represents a team in an organization type Team struct { - ID int64 `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Organization *Organization `json:"organization"` - // enum: none,read,write,admin,owner - Permission string `json:"permission"` + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Organization *Organization `json:"organization"` + Permission AccessMode `json:"permission"` + CanCreateOrgRepo bool `json:"can_create_org_repo"` + IncludesAllRepositories bool `json:"includes_all_repositories"` // example: ["repo.code","repo.issues","repo.ext_issues","repo.wiki","repo.pulls","repo.releases","repo.ext_wiki"] Units []string `json:"units"` } @@ -28,69 +29,119 @@ type ListTeamsOptions struct { } // ListOrgTeams lists all teams of an organization -func (c *Client) ListOrgTeams(org string, opt ListTeamsOptions) ([]*Team, error) { +func (c *Client) ListOrgTeams(org string, opt ListTeamsOptions) ([]*Team, *Response, error) { opt.setDefaults() teams := make([]*Team, 0, opt.PageSize) - return teams, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/teams?%s", org, opt.getURLQuery().Encode()), nil, nil, &teams) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/teams?%s", org, opt.getURLQuery().Encode()), nil, nil, &teams) + return teams, resp, err } // ListMyTeams lists all the teams of the current user -func (c *Client) ListMyTeams(opt *ListTeamsOptions) ([]*Team, error) { +func (c *Client) ListMyTeams(opt *ListTeamsOptions) ([]*Team, *Response, error) { opt.setDefaults() teams := make([]*Team, 0, opt.PageSize) - return teams, c.getParsedResponse("GET", fmt.Sprintf("/user/teams?%s", opt.getURLQuery().Encode()), nil, nil, &teams) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/teams?%s", opt.getURLQuery().Encode()), nil, nil, &teams) + return teams, resp, err } // GetTeam gets a team by ID -func (c *Client) GetTeam(id int64) (*Team, error) { +func (c *Client) GetTeam(id int64) (*Team, *Response, error) { t := new(Team) - return t, c.getParsedResponse("GET", fmt.Sprintf("/teams/%d", id), nil, nil, t) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/teams/%d", id), nil, nil, t) + return t, resp, err } // CreateTeamOption options for creating a team type CreateTeamOption struct { - Name string `json:"name"` - Description string `json:"description"` - // enum: read,write,admin - Permission string `json:"permission"` + Name string `json:"name"` + Description string `json:"description"` + Permission AccessMode `json:"permission"` + CanCreateOrgRepo bool `json:"can_create_org_repo"` + IncludesAllRepositories bool `json:"includes_all_repositories"` // example: ["repo.code","repo.issues","repo.ext_issues","repo.wiki","repo.pulls","repo.releases","repo.ext_wiki"] Units []string `json:"units"` } +// Validate the CreateTeamOption struct +func (opt CreateTeamOption) Validate() error { + if opt.Permission == AccessModeOwner { + opt.Permission = AccessModeAdmin + } else if opt.Permission != AccessModeRead && opt.Permission != AccessModeWrite && opt.Permission != AccessModeAdmin { + return fmt.Errorf("permission mode invalid") + } + if len(opt.Name) == 0 { + return fmt.Errorf("name required") + } + if len(opt.Name) > 30 { + return fmt.Errorf("name to long") + } + if len(opt.Description) > 255 { + return fmt.Errorf("description to long") + } + return nil +} + // CreateTeam creates a team for an organization -func (c *Client) CreateTeam(org string, opt CreateTeamOption) (*Team, error) { +func (c *Client) CreateTeam(org string, opt CreateTeamOption) (*Team, *Response, error) { + if err := opt.Validate(); err != nil { + return nil, nil, err + } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } t := new(Team) - return t, c.getParsedResponse("POST", fmt.Sprintf("/orgs/%s/teams", org), jsonHeader, bytes.NewReader(body), t) + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/orgs/%s/teams", org), jsonHeader, bytes.NewReader(body), t) + return t, resp, err } // EditTeamOption options for editing a team type EditTeamOption struct { - Name string `json:"name"` - Description string `json:"description"` - // enum: read,write,admin - Permission string `json:"permission"` + Name string `json:"name"` + Description *string `json:"description"` + Permission AccessMode `json:"permission"` + CanCreateOrgRepo *bool `json:"can_create_org_repo"` + IncludesAllRepositories *bool `json:"includes_all_repositories"` // example: ["repo.code","repo.issues","repo.ext_issues","repo.wiki","repo.pulls","repo.releases","repo.ext_wiki"] Units []string `json:"units"` } +// Validate the EditTeamOption struct +func (opt EditTeamOption) Validate() error { + if opt.Permission == AccessModeOwner { + opt.Permission = AccessModeAdmin + } else if opt.Permission != AccessModeRead && opt.Permission != AccessModeWrite && opt.Permission != AccessModeAdmin { + return fmt.Errorf("permission mode invalid") + } + if len(opt.Name) == 0 { + return fmt.Errorf("name required") + } + if len(opt.Name) > 30 { + return fmt.Errorf("name to long") + } + if opt.Description != nil && len(*opt.Description) > 255 { + return fmt.Errorf("description to long") + } + return nil +} + // EditTeam edits a team of an organization -func (c *Client) EditTeam(id int64, opt EditTeamOption) error { +func (c *Client) EditTeam(id int64, opt EditTeamOption) (*Response, error) { + if err := opt.Validate(); err != nil { + return nil, err + } body, err := json.Marshal(&opt) if err != nil { - return err + return nil, err } - _, err = c.getResponse("PATCH", fmt.Sprintf("/teams/%d", id), jsonHeader, bytes.NewReader(body)) - return err + _, resp, err := c.getResponse("PATCH", fmt.Sprintf("/teams/%d", id), jsonHeader, bytes.NewReader(body)) + return resp, err } // DeleteTeam deletes a team of an organization -func (c *Client) DeleteTeam(id int64) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d", id), nil, nil) - return err +func (c *Client) DeleteTeam(id int64) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d", id), nil, nil) + return resp, err } // ListTeamMembersOptions options for listing team's members @@ -99,28 +150,30 @@ type ListTeamMembersOptions struct { } // ListTeamMembers lists all members of a team -func (c *Client) ListTeamMembers(id int64, opt ListTeamMembersOptions) ([]*User, error) { +func (c *Client) ListTeamMembers(id int64, opt ListTeamMembersOptions) ([]*User, *Response, error) { opt.setDefaults() members := make([]*User, 0, opt.PageSize) - return members, c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/members?%s", id, opt.getURLQuery().Encode()), nil, nil, &members) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/members?%s", id, opt.getURLQuery().Encode()), nil, nil, &members) + return members, resp, err } // GetTeamMember gets a member of a team -func (c *Client) GetTeamMember(id int64, user string) (*User, error) { +func (c *Client) GetTeamMember(id int64, user string) (*User, *Response, error) { m := new(User) - return m, c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil, m) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil, m) + return m, resp, err } // AddTeamMember adds a member to a team -func (c *Client) AddTeamMember(id int64, user string) error { - _, err := c.getResponse("PUT", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil) - return err +func (c *Client) AddTeamMember(id int64, user string) (*Response, error) { + _, resp, err := c.getResponse("PUT", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil) + return resp, err } // RemoveTeamMember removes a member from a team -func (c *Client) RemoveTeamMember(id int64, user string) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil) - return err +func (c *Client) RemoveTeamMember(id int64, user string) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil) + return resp, err } // ListTeamRepositoriesOptions options for listing team's repositories @@ -129,20 +182,21 @@ type ListTeamRepositoriesOptions struct { } // ListTeamRepositories lists all repositories of a team -func (c *Client) ListTeamRepositories(id int64, opt ListTeamRepositoriesOptions) ([]*Repository, error) { +func (c *Client) ListTeamRepositories(id int64, opt ListTeamRepositoriesOptions) ([]*Repository, *Response, error) { opt.setDefaults() repos := make([]*Repository, 0, opt.PageSize) - return repos, c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/repos?%s", id, opt.getURLQuery().Encode()), nil, nil, &repos) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/repos?%s", id, opt.getURLQuery().Encode()), nil, nil, &repos) + return repos, resp, err } // AddTeamRepository adds a repository to a team -func (c *Client) AddTeamRepository(id int64, org, repo string) error { - _, err := c.getResponse("PUT", fmt.Sprintf("/teams/%d/repos/%s/%s", id, org, repo), nil, nil) - return err +func (c *Client) AddTeamRepository(id int64, org, repo string) (*Response, error) { + _, resp, err := c.getResponse("PUT", fmt.Sprintf("/teams/%d/repos/%s/%s", id, org, repo), nil, nil) + return resp, err } // RemoveTeamRepository removes a repository from a team -func (c *Client) RemoveTeamRepository(id int64, org, repo string) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d/repos/%s/%s", id, org, repo), nil, nil) - return err +func (c *Client) RemoveTeamRepository(id int64, org, repo string) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d/repos/%s/%s", id, org, repo), nil, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/org_type.go b/vendor/code.gitea.io/sdk/gitea/org_type.go deleted file mode 100644 index 930be186a..000000000 --- a/vendor/code.gitea.io/sdk/gitea/org_type.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2019 The Gitea Authors. All rights reserved. -// Use of this source code is governed by a MIT-style -// license that can be found in the LICENSE file. - -package gitea - -// VisibleType defines the visibility (Organization only) -type VisibleType int - -const ( - // VisibleTypePublic Visible for everyone - VisibleTypePublic VisibleType = iota - - // VisibleTypeLimited Visible for every connected user - VisibleTypeLimited - - // VisibleTypePrivate Visible only for organization's members - VisibleTypePrivate -) - -// ExtractKeysFromMapString provides a slice of keys from map -func ExtractKeysFromMapString(in map[string]VisibleType) (keys []string) { - for k := range in { - keys = append(keys, k) - } - return -} diff --git a/vendor/code.gitea.io/sdk/gitea/pull.go b/vendor/code.gitea.io/sdk/gitea/pull.go index 5005b18e5..c41ab3b01 100644 --- a/vendor/code.gitea.io/sdk/gitea/pull.go +++ b/vendor/code.gitea.io/sdk/gitea/pull.go @@ -10,6 +10,7 @@ import ( "encoding/json" "fmt" "net/url" + "strings" "time" ) @@ -35,6 +36,7 @@ type PullRequest struct { Assignee *User `json:"assignee"` Assignees []*User `json:"assignees"` State StateType `json:"state"` + IsLocked bool `json:"is_locked"` Comments int `json:"comments"` HTMLURL string `json:"html_url"` @@ -96,19 +98,21 @@ func (opt *ListPullRequestsOptions) QueryEncode() string { } // ListRepoPullRequests list PRs of one repository -func (c *Client) ListRepoPullRequests(owner, repo string, opt ListPullRequestsOptions) ([]*PullRequest, error) { +func (c *Client) ListRepoPullRequests(owner, repo string, opt ListPullRequestsOptions) ([]*PullRequest, *Response, error) { opt.setDefaults() prs := make([]*PullRequest, 0, opt.PageSize) link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls", owner, repo)) link.RawQuery = opt.QueryEncode() - return prs, c.getParsedResponse("GET", link.String(), jsonHeader, nil, &prs) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &prs) + return prs, resp, err } // GetPullRequest get information of one PR -func (c *Client) GetPullRequest(owner, repo string, index int64) (*PullRequest, error) { +func (c *Client) GetPullRequest(owner, repo string, index int64) (*PullRequest, *Response, error) { pr := new(PullRequest) - return pr, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d", owner, repo, index), nil, nil, pr) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d", owner, repo, index), nil, nil, pr) + return pr, resp, err } // CreatePullRequestOption options when creating a pull request @@ -125,14 +129,16 @@ type CreatePullRequestOption struct { } // CreatePullRequest create pull request with options -func (c *Client) CreatePullRequest(owner, repo string, opt CreatePullRequestOption) (*PullRequest, error) { +func (c *Client) CreatePullRequest(owner, repo string, opt CreatePullRequestOption) (*PullRequest, *Response, error) { body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } pr := new(PullRequest) - return pr, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/pulls", owner, repo), + resp, err := c.getParsedResponse("POST", + fmt.Sprintf("/repos/%s/%s/pulls", owner, repo), jsonHeader, bytes.NewReader(body), pr) + return pr, resp, err } // EditPullRequestOption options when modify pull request @@ -148,15 +154,33 @@ type EditPullRequestOption struct { Deadline *time.Time `json:"due_date"` } +// Validate the EditPullRequestOption struct +func (opt EditPullRequestOption) Validate(c *Client) error { + if len(opt.Title) != 0 && len(strings.TrimSpace(opt.Title)) == 0 { + return fmt.Errorf("title is empty") + } + if len(opt.Base) != 0 { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return fmt.Errorf("can not change base gitea to old") + } + } + return nil +} + // EditPullRequest modify pull request with PR id and options -func (c *Client) EditPullRequest(owner, repo string, index int64, opt EditPullRequestOption) (*PullRequest, error) { +func (c *Client) EditPullRequest(owner, repo string, index int64, opt EditPullRequestOption) (*PullRequest, *Response, error) { + if err := opt.Validate(c); err != nil { + return nil, nil, err + } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } pr := new(PullRequest) - return pr, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/pulls/%d", owner, repo, index), + resp, err := c.getParsedResponse("PATCH", + fmt.Sprintf("/repos/%s/%s/pulls/%d", owner, repo, index), jsonHeader, bytes.NewReader(body), pr) + return pr, resp, err } // MergePullRequestOption options when merging a pull request @@ -166,31 +190,64 @@ type MergePullRequestOption struct { Message string `json:"MergeMessageField"` } -// MergePullRequest merge a PR to repository by PR id -func (c *Client) MergePullRequest(owner, repo string, index int64, opt MergePullRequestOption) (bool, error) { +// Validate the MergePullRequestOption struct +func (opt MergePullRequestOption) Validate(c *Client) error { if opt.Style == MergeStyleSquash { if err := c.CheckServerVersionConstraint(">=1.11.5"); err != nil { - return false, err + return err } } + return nil +} + +// MergePullRequest merge a PR to repository by PR id +func (c *Client) MergePullRequest(owner, repo string, index int64, opt MergePullRequestOption) (bool, *Response, error) { + if err := opt.Validate(c); err != nil { + return false, nil, err + } body, err := json.Marshal(&opt) if err != nil { - return false, err + return false, nil, err } - status, err := c.getStatusCode("POST", fmt.Sprintf("/repos/%s/%s/pulls/%d/merge", owner, repo, index), jsonHeader, bytes.NewReader(body)) + status, resp, err := c.getStatusCode("POST", fmt.Sprintf("/repos/%s/%s/pulls/%d/merge", owner, repo, index), jsonHeader, bytes.NewReader(body)) if err != nil { - return false, err + return false, resp, err } - return status == 200, nil + return status == 200, resp, nil } // IsPullRequestMerged test if one PR is merged to one repository -func (c *Client) IsPullRequestMerged(owner, repo string, index int64) (bool, error) { - statusCode, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d/merge", owner, repo, index), nil, nil) +func (c *Client) IsPullRequestMerged(owner, repo string, index int64) (bool, *Response, error) { + status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d/merge", owner, repo, index), nil, nil) if err != nil { - return false, err + return false, resp, err + } + + return status == 204, resp, nil +} + +// getPullRequestDiffOrPatch gets the patch or diff file as bytes for a PR +func (c *Client) getPullRequestDiffOrPatch(owner, repo, kind string, index int64) ([]byte, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil { + r, _, err2 := c.GetRepo(owner, repo) + if err2 != nil { + return nil, nil, err + } + if r.Private { + return nil, nil, err + } + return c.getWebResponse("GET", fmt.Sprintf("/%s/%s/pulls/%d.%s", owner, repo, index, kind), nil) } + return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d.%s", owner, repo, index, kind), nil, nil) +} + +// GetPullRequestPatch gets the .patch file as bytes for a PR +func (c *Client) GetPullRequestPatch(owner, repo string, index int64) ([]byte, *Response, error) { + return c.getPullRequestDiffOrPatch(owner, repo, "patch", index) +} - return statusCode == 204, nil +// GetPullRequestDiff gets the .diff file as bytes for a PR +func (c *Client) GetPullRequestDiff(owner, repo string, index int64) ([]byte, *Response, error) { + return c.getPullRequestDiffOrPatch(owner, repo, "diff", index) } diff --git a/vendor/code.gitea.io/sdk/gitea/pull_review.go b/vendor/code.gitea.io/sdk/gitea/pull_review.go index 9ff708a12..41cf72944 100644 --- a/vendor/code.gitea.io/sdk/gitea/pull_review.go +++ b/vendor/code.gitea.io/sdk/gitea/pull_review.go @@ -9,6 +9,7 @@ import ( "encoding/json" "fmt" "net/url" + "strings" "time" ) @@ -32,16 +33,19 @@ const ( // PullReview represents a pull request review type PullReview struct { - ID int64 `json:"id"` - Reviewer *User `json:"user"` - State ReviewStateType `json:"state"` - Body string `json:"body"` - CommitID string `json:"commit_id"` - Stale bool `json:"stale"` - Official bool `json:"official"` - CodeCommentsCount int `json:"comments_count"` - // swagger:strfmt date-time - Submitted time.Time `json:"submitted_at"` + ID int64 `json:"id"` + Reviewer *User `json:"user"` + ReviewerTeam *Team `json:"team"` + State ReviewStateType `json:"state"` + Body string `json:"body"` + CommitID string `json:"commit_id"` + // Stale indicates if the pull has changed since the review + Stale bool `json:"stale"` + // Official indicates if the review counts towards the required approval limit, if PR base is a protected branch + Official bool `json:"official"` + Dismissed bool `json:"dismissed"` + CodeCommentsCount int `json:"comments_count"` + Submitted time.Time `json:"submitted_at"` HTMLURL string `json:"html_url"` HTMLPullURL string `json:"pull_request_url"` @@ -54,9 +58,7 @@ type PullReviewComment struct { Reviewer *User `json:"user"` ReviewID int64 `json:"pull_request_review_id"` - // swagger:strfmt date-time Created time.Time `json:"created_at"` - // swagger:strfmt date-time Updated time.Time `json:"updated_at"` Path string `json:"path"` @@ -95,15 +97,58 @@ type SubmitPullReviewOptions struct { Body string `json:"body"` } +// DismissPullReviewOptions are options to dismiss a pull review +type DismissPullReviewOptions struct { + Message string `json:"message"` +} + +// PullReviewRequestOptions are options to add or remove pull review requests +type PullReviewRequestOptions struct { + Reviewers []string `json:"reviewers"` + TeamReviewers []string `json:"team_reviewers"` +} + // ListPullReviewsOptions options for listing PullReviews type ListPullReviewsOptions struct { ListOptions } +// Validate the CreatePullReviewOptions struct +func (opt CreatePullReviewOptions) Validate() error { + if opt.State != ReviewStateApproved && len(strings.TrimSpace(opt.Body)) == 0 { + return fmt.Errorf("body is empty") + } + for i := range opt.Comments { + if err := opt.Comments[i].Validate(); err != nil { + return err + } + } + return nil +} + +// Validate the SubmitPullReviewOptions struct +func (opt SubmitPullReviewOptions) Validate() error { + if opt.State != ReviewStateApproved && len(strings.TrimSpace(opt.Body)) == 0 { + return fmt.Errorf("body is empty") + } + return nil +} + +// Validate the CreatePullReviewComment struct +func (opt CreatePullReviewComment) Validate() error { + if len(strings.TrimSpace(opt.Body)) == 0 { + return fmt.Errorf("body is empty") + } + if opt.NewLineNum != 0 && opt.OldLineNum != 0 { + return fmt.Errorf("old and new line num are set, cant identify the code comment position") + } + return nil +} + // ListPullReviews lists all reviews of a pull request -func (c *Client) ListPullReviews(owner, repo string, index int64, opt ListPullReviewsOptions) ([]*PullReview, error) { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return nil, err +func (c *Client) ListPullReviews(owner, repo string, index int64, opt ListPullReviewsOptions) ([]*PullReview, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, nil, err } opt.setDefaults() rs := make([]*PullReview, 0, opt.PageSize) @@ -111,74 +156,139 @@ func (c *Client) ListPullReviews(owner, repo string, index int64, opt ListPullRe link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews", owner, repo, index)) link.RawQuery = opt.ListOptions.getURLQuery().Encode() - return rs, c.getParsedResponse("GET", link.String(), jsonHeader, nil, &rs) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &rs) + return rs, resp, err } // GetPullReview gets a specific review of a pull request -func (c *Client) GetPullReview(owner, repo string, index, id int64) (*PullReview, error) { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return nil, err +func (c *Client) GetPullReview(owner, repo string, index, id int64) (*PullReview, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, nil, err } r := new(PullReview) - return r, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id), jsonHeader, nil, &r) -} - -// ListPullReviewsCommentsOptions options for listing PullReviewsComments -type ListPullReviewsCommentsOptions struct { - ListOptions + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id), jsonHeader, nil, &r) + return r, resp, err } // ListPullReviewComments lists all comments of a pull request review -func (c *Client) ListPullReviewComments(owner, repo string, index, id int64, opt ListPullReviewsCommentsOptions) ([]*PullReviewComment, error) { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return nil, err +func (c *Client) ListPullReviewComments(owner, repo string, index, id int64) ([]*PullReviewComment, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, nil, err } - opt.setDefaults() - rcl := make([]*PullReviewComment, 0, opt.PageSize) - + rcl := make([]*PullReviewComment, 0, 4) link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d/comments", owner, repo, index, id)) - link.RawQuery = opt.ListOptions.getURLQuery().Encode() - return rcl, c.getParsedResponse("GET", link.String(), jsonHeader, nil, &rcl) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &rcl) + return rcl, resp, err } // DeletePullReview delete a specific review from a pull request -func (c *Client) DeletePullReview(owner, repo string, index, id int64) error { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return err +func (c *Client) DeletePullReview(owner, repo string, index, id int64) (*Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, err } - _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id), jsonHeader, nil) - return err + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id), jsonHeader, nil) + return resp, err } // CreatePullReview create a review to an pull request -func (c *Client) CreatePullReview(owner, repo string, index int64, opt CreatePullReviewOptions) (*PullReview, error) { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return nil, err +func (c *Client) CreatePullReview(owner, repo string, index int64, opt CreatePullReviewOptions) (*PullReview, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, nil, err + } + if err := opt.Validate(); err != nil { + return nil, nil, err } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } r := new(PullReview) - return r, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews", owner, repo, index), + resp, err := c.getParsedResponse("POST", + fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews", owner, repo, index), jsonHeader, bytes.NewReader(body), r) + return r, resp, err } // SubmitPullReview submit a pending review to an pull request -func (c *Client) SubmitPullReview(owner, repo string, index, id int64, opt SubmitPullReviewOptions) (*PullReview, error) { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return nil, err +func (c *Client) SubmitPullReview(owner, repo string, index, id int64, opt SubmitPullReviewOptions) (*PullReview, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, nil, err + } + if err := opt.Validate(); err != nil { + return nil, nil, err } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } r := new(PullReview) - return r, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id), + resp, err := c.getParsedResponse("POST", + fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id), jsonHeader, bytes.NewReader(body), r) + return r, resp, err +} + +// CreateReviewRequests create review requests to an pull request +func (c *Client) CreateReviewRequests(owner, repo string, index int64, opt PullReviewRequestOptions) (*Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil { + return nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, err + } + + _, resp, err := c.getResponse("POST", + fmt.Sprintf("/repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, index), + jsonHeader, bytes.NewReader(body)) + return resp, err +} + +// DeleteReviewRequests delete review requests to an pull request +func (c *Client) DeleteReviewRequests(owner, repo string, index int64, opt PullReviewRequestOptions) (*Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil { + return nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, err + } + + _, resp, err := c.getResponse("DELETE", + fmt.Sprintf("/repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, index), + jsonHeader, bytes.NewReader(body)) + return resp, err +} + +// DismissPullReview dismiss a review for a pull request +func (c *Client) DismissPullReview(owner, repo string, index, id int64, opt DismissPullReviewOptions) (*Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil { + return nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, err + } + + _, resp, err := c.getResponse("POST", + fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d/dismissals", owner, repo, index, id), + jsonHeader, bytes.NewReader(body)) + return resp, err +} + +// UnDismissPullReview cancel to dismiss a review for a pull request +func (c *Client) UnDismissPullReview(owner, repo string, index, id int64) (*Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil { + return nil, err + } + + _, resp, err := c.getResponse("POST", + fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d/undismissals", owner, repo, index, id), + jsonHeader, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/release.go b/vendor/code.gitea.io/sdk/gitea/release.go index fe5c023de..741cbceae 100644 --- a/vendor/code.gitea.io/sdk/gitea/release.go +++ b/vendor/code.gitea.io/sdk/gitea/release.go @@ -8,6 +8,8 @@ import ( "bytes" "encoding/json" "fmt" + "net/http" + "strings" "time" ) @@ -19,6 +21,7 @@ type Release struct { Title string `json:"name"` Note string `json:"body"` URL string `json:"url"` + HTMLURL string `json:"html_url"` TarURL string `json:"tarball_url"` ZipURL string `json:"zipball_url"` IsDraft bool `json:"draft"` @@ -35,22 +38,34 @@ type ListReleasesOptions struct { } // ListReleases list releases of a repository -func (c *Client) ListReleases(user, repo string, opt ListReleasesOptions) ([]*Release, error) { +func (c *Client) ListReleases(user, repo string, opt ListReleasesOptions) ([]*Release, *Response, error) { opt.setDefaults() releases := make([]*Release, 0, opt.PageSize) - err := c.getParsedResponse("GET", + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/releases?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &releases) - return releases, err + return releases, resp, err } -// GetRelease get a release of a repository -func (c *Client) GetRelease(user, repo string, id int64) (*Release, error) { +// GetRelease get a release of a repository by id +func (c *Client) GetRelease(user, repo string, id int64) (*Release, *Response, error) { r := new(Release) - err := c.getParsedResponse("GET", + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id), + jsonHeader, nil, &r) + return r, resp, err +} + +// GetReleaseByTag get a release of a repository by tag +func (c *Client) GetReleaseByTag(user, repo string, tag string) (*Release, *Response, error) { + if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil { + return c.fallbackGetReleaseByTag(user, repo, tag) + } + r := new(Release) + resp, err := c.getParsedResponse("GET", + fmt.Sprintf("/repos/%s/%s/releases/tags/%s", user, repo, tag), nil, nil, &r) - return r, err + return r, resp, err } // CreateReleaseOption options when creating a release @@ -63,17 +78,28 @@ type CreateReleaseOption struct { IsPrerelease bool `json:"prerelease"` } +// Validate the CreateReleaseOption struct +func (opt CreateReleaseOption) Validate() error { + if len(strings.TrimSpace(opt.Title)) == 0 { + return fmt.Errorf("title is empty") + } + return nil +} + // CreateRelease create a release -func (c *Client) CreateRelease(user, repo string, form CreateReleaseOption) (*Release, error) { - body, err := json.Marshal(form) +func (c *Client) CreateRelease(user, repo string, opt CreateReleaseOption) (*Release, *Response, error) { + if err := opt.Validate(); err != nil { + return nil, nil, err + } + body, err := json.Marshal(opt) if err != nil { - return nil, err + return nil, nil, err } r := new(Release) - err = c.getParsedResponse("POST", + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/releases", user, repo), jsonHeader, bytes.NewReader(body), r) - return r, err + return r, resp, err } // EditReleaseOption options when editing a release @@ -87,22 +113,53 @@ type EditReleaseOption struct { } // EditRelease edit a release -func (c *Client) EditRelease(user, repo string, id int64, form EditReleaseOption) (*Release, error) { +func (c *Client) EditRelease(user, repo string, id int64, form EditReleaseOption) (*Release, *Response, error) { body, err := json.Marshal(form) if err != nil { - return nil, err + return nil, nil, err } r := new(Release) - err = c.getParsedResponse("PATCH", + resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id), jsonHeader, bytes.NewReader(body), r) - return r, err + return r, resp, err } -// DeleteRelease delete a release from a repository -func (c *Client) DeleteRelease(user, repo string, id int64) error { - _, err := c.getResponse("DELETE", +// DeleteRelease delete a release from a repository, keeping its tag +func (c *Client) DeleteRelease(user, repo string, id int64) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id), nil, nil) - return err + return resp, err +} + +// DeleteReleaseByTag deletes a release frm a repository by tag +func (c *Client) DeleteReleaseByTag(user, repo string, tag string) (*Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil { + return nil, err + } + _, resp, err := c.getResponse("DELETE", + fmt.Sprintf("/repos/%s/%s/releases/tags/%s", user, repo, tag), + nil, nil) + return resp, err +} + +// fallbackGetReleaseByTag is fallback for old gitea installations ( < 1.13.0 ) +func (c *Client) fallbackGetReleaseByTag(user, repo string, tag string) (*Release, *Response, error) { + for i := 1; ; i++ { + rl, resp, err := c.ListReleases(user, repo, ListReleasesOptions{ListOptions{Page: i}}) + if err != nil { + return nil, resp, err + } + if len(rl) == 0 { + return nil, + &Response{&http.Response{StatusCode: 404}}, + fmt.Errorf("release with tag '%s' not found", tag) + } + for _, r := range rl { + if r.TagName == tag { + return r, resp, nil + } + } + } } diff --git a/vendor/code.gitea.io/sdk/gitea/repo.go b/vendor/code.gitea.io/sdk/gitea/repo.go index 80f24b889..50a131517 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo.go +++ b/vendor/code.gitea.io/sdk/gitea/repo.go @@ -1,4 +1,5 @@ // Copyright 2014 The Gogs Authors. All rights reserved. +// Copyright 2020 The Gitea Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. @@ -8,7 +9,9 @@ import ( "bytes" "encoding/json" "fmt" + "io" "net/url" + "strings" "time" ) @@ -19,61 +22,126 @@ type Permission struct { Pull bool `json:"pull"` } +// InternalTracker represents settings for internal tracker +type InternalTracker struct { + // Enable time tracking (Built-in issue tracker) + EnableTimeTracker bool `json:"enable_time_tracker"` + // Let only contributors track time (Built-in issue tracker) + AllowOnlyContributorsToTrackTime bool `json:"allow_only_contributors_to_track_time"` + // Enable dependencies for issues and pull requests (Built-in issue tracker) + EnableIssueDependencies bool `json:"enable_issue_dependencies"` +} + +// ExternalTracker represents settings for external tracker +type ExternalTracker struct { + // URL of external issue tracker. + ExternalTrackerURL string `json:"external_tracker_url"` + // External Issue Tracker URL Format. Use the placeholders {user}, {repo} and {index} for the username, repository name and issue index. + ExternalTrackerFormat string `json:"external_tracker_format"` + // External Issue Tracker Number Format, either `numeric` or `alphanumeric` + ExternalTrackerStyle string `json:"external_tracker_style"` +} + +// ExternalWiki represents setting for external wiki +type ExternalWiki struct { + // URL of external wiki. + ExternalWikiURL string `json:"external_wiki_url"` +} + // Repository represents a repository type Repository struct { - ID int64 `json:"id"` - Owner *User `json:"owner"` - Name string `json:"name"` - FullName string `json:"full_name"` - Description string `json:"description"` - Empty bool `json:"empty"` - Private bool `json:"private"` - Fork bool `json:"fork"` - Parent *Repository `json:"parent"` - Mirror bool `json:"mirror"` - Size int `json:"size"` - HTMLURL string `json:"html_url"` - SSHURL string `json:"ssh_url"` - CloneURL string `json:"clone_url"` - OriginalURL string `json:"original_url"` - Website string `json:"website"` - Stars int `json:"stars_count"` - Forks int `json:"forks_count"` - Watchers int `json:"watchers_count"` - OpenIssues int `json:"open_issues_count"` - DefaultBranch string `json:"default_branch"` - Archived bool `json:"archived"` - Created time.Time `json:"created_at"` - Updated time.Time `json:"updated_at"` - Permissions *Permission `json:"permissions,omitempty"` - HasIssues bool `json:"has_issues"` - HasWiki bool `json:"has_wiki"` - HasPullRequests bool `json:"has_pull_requests"` - IgnoreWhitespaceConflicts bool `json:"ignore_whitespace_conflicts"` - AllowMerge bool `json:"allow_merge_commits"` - AllowRebase bool `json:"allow_rebase"` - AllowRebaseMerge bool `json:"allow_rebase_explicit"` - AllowSquash bool `json:"allow_squash_merge"` - AvatarURL string `json:"avatar_url"` + ID int64 `json:"id"` + Owner *User `json:"owner"` + Name string `json:"name"` + FullName string `json:"full_name"` + Description string `json:"description"` + Empty bool `json:"empty"` + Private bool `json:"private"` + Fork bool `json:"fork"` + Template bool `json:"template"` + Parent *Repository `json:"parent"` + Mirror bool `json:"mirror"` + Size int `json:"size"` + HTMLURL string `json:"html_url"` + SSHURL string `json:"ssh_url"` + CloneURL string `json:"clone_url"` + OriginalURL string `json:"original_url"` + Website string `json:"website"` + Stars int `json:"stars_count"` + Forks int `json:"forks_count"` + Watchers int `json:"watchers_count"` + OpenIssues int `json:"open_issues_count"` + OpenPulls int `json:"open_pr_counter"` + Releases int `json:"release_counter"` + DefaultBranch string `json:"default_branch"` + Archived bool `json:"archived"` + Created time.Time `json:"created_at"` + Updated time.Time `json:"updated_at"` + Permissions *Permission `json:"permissions,omitempty"` + HasIssues bool `json:"has_issues"` + InternalTracker *InternalTracker `json:"internal_tracker,omitempty"` + ExternalTracker *ExternalTracker `json:"external_tracker,omitempty"` + HasWiki bool `json:"has_wiki"` + ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"` + HasPullRequests bool `json:"has_pull_requests"` + HasProjects bool `json:"has_projects"` + IgnoreWhitespaceConflicts bool `json:"ignore_whitespace_conflicts"` + AllowMerge bool `json:"allow_merge_commits"` + AllowRebase bool `json:"allow_rebase"` + AllowRebaseMerge bool `json:"allow_rebase_explicit"` + AllowSquash bool `json:"allow_squash_merge"` + AvatarURL string `json:"avatar_url"` + Internal bool `json:"internal"` + MirrorInterval string `json:"mirror_interval"` } +// RepoType represent repo type +type RepoType string + +const ( + // RepoTypeNone dont specify a type + RepoTypeNone RepoType = "" + // RepoTypeSource is the default repo type + RepoTypeSource RepoType = "source" + // RepoTypeFork is a repo witch was forked from an other one + RepoTypeFork RepoType = "fork" + // RepoTypeMirror represents an mirror repo + RepoTypeMirror RepoType = "mirror" +) + +// TrustModel represent how git signatures are handled in a repository +type TrustModel string + +const ( + // TrustModelDefault use TM set by global config + TrustModelDefault TrustModel = "default" + // TrustModelCollaborator gpg signature has to be owned by a repo collaborator + TrustModelCollaborator TrustModel = "collaborator" + // TrustModelCommitter gpg signature has to match committer + TrustModelCommitter TrustModel = "committer" + // TrustModelCollaboratorCommitter gpg signature has to match committer and owned by a repo collaborator + TrustModelCollaboratorCommitter TrustModel = "collaboratorcommitter" +) + // ListReposOptions options for listing repositories type ListReposOptions struct { ListOptions } // ListMyRepos lists all repositories for the authenticated user that has access to. -func (c *Client) ListMyRepos(opt ListReposOptions) ([]*Repository, error) { +func (c *Client) ListMyRepos(opt ListReposOptions) ([]*Repository, *Response, error) { opt.setDefaults() repos := make([]*Repository, 0, opt.PageSize) - return repos, c.getParsedResponse("GET", fmt.Sprintf("/user/repos?%s", opt.getURLQuery().Encode()), nil, nil, &repos) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/repos?%s", opt.getURLQuery().Encode()), nil, nil, &repos) + return repos, resp, err } // ListUserRepos list all repositories of one user by user's name -func (c *Client) ListUserRepos(user string, opt ListReposOptions) ([]*Repository, error) { +func (c *Client) ListUserRepos(user string, opt ListReposOptions) ([]*Repository, *Response, error) { opt.setDefaults() repos := make([]*Repository, 0, opt.PageSize) - return repos, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/repos?%s", user, opt.getURLQuery().Encode()), nil, nil, &repos) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/repos?%s", user, opt.getURLQuery().Encode()), nil, nil, &repos) + return repos, resp, err } // ListOrgReposOptions options for a organization's repositories @@ -82,26 +150,62 @@ type ListOrgReposOptions struct { } // ListOrgRepos list all repositories of one organization by organization's name -func (c *Client) ListOrgRepos(org string, opt ListOrgReposOptions) ([]*Repository, error) { +func (c *Client) ListOrgRepos(org string, opt ListOrgReposOptions) ([]*Repository, *Response, error) { opt.setDefaults() repos := make([]*Repository, 0, opt.PageSize) - return repos, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/repos?%s", org, opt.getURLQuery().Encode()), nil, nil, &repos) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/repos?%s", org, opt.getURLQuery().Encode()), nil, nil, &repos) + return repos, resp, err } // SearchRepoOptions options for searching repositories type SearchRepoOptions struct { ListOptions - Keyword string - Topic bool - IncludeDesc bool - UID int64 - PriorityOwnerID int64 - StarredBy int64 - Private bool - Template bool - Mode string - Exclusive bool - Sort string + + // The keyword to query + Keyword string + // Limit search to repositories with keyword as topic + KeywordIsTopic bool + // Include search of keyword within repository description + KeywordInDescription bool + + /* + User Filter + */ + + // Repo Owner + OwnerID int64 + // Stared By UserID + StarredByUserID int64 + + /* + Repo Attributes + */ + + // pubic, private or all repositories (defaults to all) + IsPrivate *bool + // archived, non-archived or all repositories (defaults to all) + IsArchived *bool + // Exclude template repos from search + ExcludeTemplate bool + // Filter by "fork", "source", "mirror" + Type RepoType + + /* + Sort Filters + */ + + // sort repos by attribute. Supported values are "alpha", "created", "updated", "size", and "id". Default is "alpha" + Sort string + // sort order, either "asc" (ascending) or "desc" (descending). Default is "asc", ignored if "sort" is not specified. + Order string + // Repo owner to prioritize in the results + PrioritizedByOwnerID int64 + + /* + Cover EdgeCases + */ + // if set all other options are ignored and this string is used as query + RawQuery string } // QueryEncode turns options into querystring argument @@ -110,34 +214,46 @@ func (opt *SearchRepoOptions) QueryEncode() string { if opt.Keyword != "" { query.Add("q", opt.Keyword) } - - query.Add("topic", fmt.Sprintf("%t", opt.Topic)) - query.Add("includeDesc", fmt.Sprintf("%t", opt.IncludeDesc)) - - if opt.UID > 0 { - query.Add("uid", fmt.Sprintf("%d", opt.UID)) + if opt.KeywordIsTopic { + query.Add("topic", "true") } - - if opt.PriorityOwnerID > 0 { - query.Add("priority_owner_id", fmt.Sprintf("%d", opt.PriorityOwnerID)) + if opt.KeywordInDescription { + query.Add("includeDesc", "true") } - if opt.StarredBy > 0 { - query.Add("starredBy", fmt.Sprintf("%d", opt.StarredBy)) + // User Filter + if opt.OwnerID > 0 { + query.Add("uid", fmt.Sprintf("%d", opt.OwnerID)) + query.Add("exclusive", "true") } - - query.Add("private", fmt.Sprintf("%t", opt.Private)) - query.Add("template", fmt.Sprintf("%t", opt.Template)) - - if opt.Mode != "" { - query.Add("mode", opt.Mode) + if opt.StarredByUserID > 0 { + query.Add("starredBy", fmt.Sprintf("%d", opt.StarredByUserID)) } - query.Add("exclusive", fmt.Sprintf("%t", opt.Exclusive)) + // Repo Attributes + if opt.IsPrivate != nil { + query.Add("is_private", fmt.Sprintf("%v", opt.IsPrivate)) + } + if opt.IsArchived != nil { + query.Add("archived", fmt.Sprintf("%v", opt.IsArchived)) + } + if opt.ExcludeTemplate { + query.Add("template", "false") + } + if len(opt.Type) != 0 { + query.Add("mode", string(opt.Type)) + } + // Sort Filters if opt.Sort != "" { query.Add("sort", opt.Sort) } + if opt.PrioritizedByOwnerID > 0 { + query.Add("priority_owner_id", fmt.Sprintf("%d", opt.PrioritizedByOwnerID)) + } + if opt.Order != "" { + query.Add("order", opt.Order) + } return query.Encode() } @@ -147,21 +263,33 @@ type searchRepoResponse struct { } // SearchRepos searches for repositories matching the given filters -func (c *Client) SearchRepos(opt SearchRepoOptions) ([]*Repository, error) { +func (c *Client) SearchRepos(opt SearchRepoOptions) ([]*Repository, *Response, error) { opt.setDefaults() - resp := new(searchRepoResponse) + repos := new(searchRepoResponse) link, _ := url.Parse("/repos/search") - link.RawQuery = opt.QueryEncode() - err := c.getParsedResponse("GET", link.String(), nil, nil, &resp) - return resp.Repos, err + if len(opt.RawQuery) != 0 { + link.RawQuery = opt.RawQuery + } else { + link.RawQuery = opt.QueryEncode() + // IsPrivate only works on gitea >= 1.12.0 + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil && opt.IsPrivate != nil { + if *opt.IsPrivate { + // private repos only not supported on gitea <= 1.11.x + return nil, nil, err + } + link.Query().Add("private", "false") + } + } + + resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &repos) + return repos.Repos, resp, err } // CreateRepoOption options when creating repository type CreateRepoOption struct { // Name of the repository to create - // Name string `json:"name"` // Description of the repository to create Description string `json:"description"` @@ -171,6 +299,8 @@ type CreateRepoOption struct { IssueLabels string `json:"issue_labels"` // Whether the repository should be auto-intialized? AutoInit bool `json:"auto_init"` + // Whether the repository is template + Template bool `json:"template"` // Gitignores to use Gitignores string `json:"gitignores"` // License to use @@ -179,32 +309,65 @@ type CreateRepoOption struct { Readme string `json:"readme"` // DefaultBranch of the repository (used when initializes and in template) DefaultBranch string `json:"default_branch"` + // TrustModel of the repository + TrustModel TrustModel `json:"trust_model"` +} + +// Validate the CreateRepoOption struct +func (opt CreateRepoOption) Validate(c *Client) error { + if len(strings.TrimSpace(opt.Name)) == 0 { + return fmt.Errorf("name is empty") + } + if len(opt.Name) > 100 { + return fmt.Errorf("name has more than 100 chars") + } + if len(opt.Description) > 255 { + return fmt.Errorf("name has more than 255 chars") + } + if len(opt.DefaultBranch) > 100 { + return fmt.Errorf("name has more than 100 chars") + } + if len(opt.TrustModel) != 0 { + if err := c.CheckServerVersionConstraint(">=1.13.0"); err != nil { + return err + } + } + return nil } // CreateRepo creates a repository for authenticated user. -func (c *Client) CreateRepo(opt CreateRepoOption) (*Repository, error) { +func (c *Client) CreateRepo(opt CreateRepoOption) (*Repository, *Response, error) { + if err := opt.Validate(c); err != nil { + return nil, nil, err + } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } repo := new(Repository) - return repo, c.getParsedResponse("POST", "/user/repos", jsonHeader, bytes.NewReader(body), repo) + resp, err := c.getParsedResponse("POST", "/user/repos", jsonHeader, bytes.NewReader(body), repo) + return repo, resp, err } // CreateOrgRepo creates an organization repository for authenticated user. -func (c *Client) CreateOrgRepo(org string, opt CreateRepoOption) (*Repository, error) { +func (c *Client) CreateOrgRepo(org string, opt CreateRepoOption) (*Repository, *Response, error) { + if err := opt.Validate(c); err != nil { + return nil, nil, err + } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } repo := new(Repository) - return repo, c.getParsedResponse("POST", fmt.Sprintf("/org/%s/repos", org), jsonHeader, bytes.NewReader(body), repo) + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/org/%s/repos", org), jsonHeader, bytes.NewReader(body), repo) + return repo, resp, err } // GetRepo returns information of a repository of given owner. -func (c *Client) GetRepo(owner, reponame string) (*Repository, error) { +func (c *Client) GetRepo(owner, reponame string) (*Repository, *Response, error) { repo := new(Repository) - return repo, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s", owner, reponame), nil, nil, repo) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s", owner, reponame), nil, nil, repo) + return repo, resp, err } // EditRepoOption options when editing a repository's properties @@ -219,14 +382,24 @@ type EditRepoOption struct { // Note: you will get a 422 error if the organization restricts changing repository visibility to organization // owners and a non-owner tries to change the value of private. Private *bool `json:"private,omitempty"` + // either `true` to make this repository a template or `false` to make it a normal repository + Template *bool `json:"template,omitempty"` // either `true` to enable issues for this repository or `false` to disable them. HasIssues *bool `json:"has_issues,omitempty"` + // set this structure to configure internal issue tracker (requires has_issues) + InternalTracker *InternalTracker `json:"internal_tracker,omitempty"` + // set this structure to use external issue tracker (requires has_issues) + ExternalTracker *ExternalTracker `json:"external_tracker,omitempty"` // either `true` to enable the wiki for this repository or `false` to disable it. HasWiki *bool `json:"has_wiki,omitempty"` + // set this structure to use external wiki instead of internal (requires has_wiki) + ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"` // sets the default branch for this repository. DefaultBranch *string `json:"default_branch,omitempty"` // either `true` to allow pull requests, or `false` to prevent pull request. HasPullRequests *bool `json:"has_pull_requests,omitempty"` + // either `true` to enable project unit, or `false` to disable them. + HasProjects *bool `json:"has_projects,omitempty"` // either `true` to ignore whitespace for conflicts, or `false` to not ignore whitespace. `has_pull_requests` must be `true`. IgnoreWhitespaceConflicts *bool `json:"ignore_whitespace_conflicts,omitempty"` // either `true` to allow merging pull requests with a merge commit, or `false` to prevent merging pull requests with merge commits. `has_pull_requests` must be `true`. @@ -239,52 +412,76 @@ type EditRepoOption struct { AllowSquash *bool `json:"allow_squash_merge,omitempty"` // set to `true` to archive this repository. Archived *bool `json:"archived,omitempty"` + // set to a string like `8h30m0s` to set the mirror interval time + MirrorInterval *string `json:"mirror_interval,omitempty"` } // EditRepo edit the properties of a repository -func (c *Client) EditRepo(owner, reponame string, opt EditRepoOption) (*Repository, error) { +func (c *Client) EditRepo(owner, reponame string, opt EditRepoOption) (*Repository, *Response, error) { body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } repo := new(Repository) - return repo, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s", owner, reponame), jsonHeader, bytes.NewReader(body), repo) + resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s", owner, reponame), jsonHeader, bytes.NewReader(body), repo) + return repo, resp, err } // DeleteRepo deletes a repository of user or organization. -func (c *Client) DeleteRepo(owner, repo string) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s", owner, repo), nil, nil) - return err +func (c *Client) DeleteRepo(owner, repo string) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s", owner, repo), nil, nil) + return resp, err } -// MigrateRepoOption options for migrating a repository from an external service -type MigrateRepoOption struct { - CloneAddr string `json:"clone_addr"` - AuthUsername string `json:"auth_username"` - AuthPassword string `json:"auth_password"` - UID int `json:"uid"` - RepoName string `json:"repo_name"` - Mirror bool `json:"mirror"` - Private bool `json:"private"` - Description string `json:"description"` +// MirrorSync adds a mirrored repository to the mirror sync queue. +func (c *Client) MirrorSync(owner, repo string) (*Response, error) { + _, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/mirror-sync", owner, repo), nil, nil) + return resp, err } -// MigrateRepo migrates a repository from other Git hosting sources for the -// authenticated user. -// -// To migrate a repository for a organization, the authenticated user must be a -// owner of the specified organization. -func (c *Client) MigrateRepo(opt MigrateRepoOption) (*Repository, error) { - body, err := json.Marshal(&opt) +// GetRepoLanguages return language stats of a repo +func (c *Client) GetRepoLanguages(owner, repo string) (map[string]int64, *Response, error) { + langMap := make(map[string]int64) + + data, resp, err := c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/languages", owner, repo), jsonHeader, nil) if err != nil { - return nil, err + return nil, resp, err } - repo := new(Repository) - return repo, c.getParsedResponse("POST", "/repos/migrate", jsonHeader, bytes.NewReader(body), repo) + if err = json.Unmarshal(data, &langMap); err != nil { + return nil, resp, err + } + return langMap, resp, nil } -// MirrorSync adds a mirrored repository to the mirror sync queue. -func (c *Client) MirrorSync(owner, repo string) error { - _, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/mirror-sync", owner, repo), nil, nil) - return err +// ArchiveType represent supported archive formats by gitea +type ArchiveType string + +const ( + // ZipArchive represent zip format + ZipArchive ArchiveType = ".zip" + // TarGZArchive represent tar.gz format + TarGZArchive ArchiveType = ".tar.gz" +) + +// GetArchive get an archive of a repository by git reference +// e.g.: ref -> master, 70b7c74b33, v1.2.1, ... +func (c *Client) GetArchive(owner, repo, ref string, ext ArchiveType) ([]byte, *Response, error) { + return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/archive/%s%s", owner, repo, url.PathEscape(ref), ext), nil, nil) +} + +// GetArchiveReader gets a `git archive` for a particular tree-ish git reference +// such as a branch name (`master`), a commit hash (`70b7c74b33`), a tag +// (`v1.2.1`). The archive is returned as a byte stream in a ReadCloser. It is +// the responsibility of the client to close the reader. +func (c *Client) GetArchiveReader(owner, repo, ref string, ext ArchiveType) (io.ReadCloser, *Response, error) { + resp, err := c.doRequest("GET", fmt.Sprintf("/repos/%s/%s/archive/%s%s", owner, repo, url.PathEscape(ref), ext), nil, nil) + if err != nil { + return nil, resp, err + } + + if _, err := statusCodeToErr(resp); err != nil { + return nil, resp, err + } + + return resp.Body, resp, nil } diff --git a/vendor/code.gitea.io/sdk/gitea/repo_branch.go b/vendor/code.gitea.io/sdk/gitea/repo_branch.go index 084a6ce7c..6b0eec27e 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_branch.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_branch.go @@ -6,6 +6,8 @@ package gitea import ( + "bytes" + "encoding/json" "fmt" "time" ) @@ -63,29 +65,70 @@ type ListRepoBranchesOptions struct { } // ListRepoBranches list all the branches of one repository -func (c *Client) ListRepoBranches(user, repo string, opt ListRepoBranchesOptions) ([]*Branch, error) { +func (c *Client) ListRepoBranches(user, repo string, opt ListRepoBranchesOptions) ([]*Branch, *Response, error) { opt.setDefaults() branches := make([]*Branch, 0, opt.PageSize) - return branches, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &branches) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &branches) + return branches, resp, err } // GetRepoBranch get one branch's information of one repository -func (c *Client) GetRepoBranch(user, repo, branch string) (*Branch, error) { +func (c *Client) GetRepoBranch(user, repo, branch string) (*Branch, *Response, error) { b := new(Branch) - if err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil, &b); err != nil { - return nil, err + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil, &b) + if err != nil { + return nil, resp, err } - return b, nil + return b, resp, nil } // DeleteRepoBranch delete a branch in a repository -func (c *Client) DeleteRepoBranch(user, repo, branch string) (bool, error) { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return false, err +func (c *Client) DeleteRepoBranch(user, repo, branch string) (bool, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return false, nil, err + } + status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil) + if err != nil { + return false, resp, err + } + return status == 204, resp, nil +} + +// CreateBranchOption options when creating a branch in a repository +type CreateBranchOption struct { + // Name of the branch to create + BranchName string `json:"new_branch_name"` + // Name of the old branch to create from (optional) + OldBranchName string `json:"old_branch_name"` +} + +// Validate the CreateBranchOption struct +func (opt CreateBranchOption) Validate() error { + if len(opt.BranchName) == 0 { + return fmt.Errorf("BranchName is empty") + } + if len(opt.BranchName) > 100 { + return fmt.Errorf("BranchName to long") + } + if len(opt.OldBranchName) > 100 { + return fmt.Errorf("OldBranchName to long") + } + return nil +} + +// CreateBranch creates a branch for a user's repository +func (c *Client) CreateBranch(owner, repo string, opt CreateBranchOption) (*Branch, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil { + return nil, nil, err + } + if err := opt.Validate(); err != nil { + return nil, nil, err } - status, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil) + body, err := json.Marshal(&opt) if err != nil { - return false, err + return nil, nil, err } - return status == 204, nil + branch := new(Branch) + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/branches", owner, repo), jsonHeader, bytes.NewReader(body), branch) + return branch, resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/repo_branch_protection.go b/vendor/code.gitea.io/sdk/gitea/repo_branch_protection.go index b7ef96c74..3e1d01aa6 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_branch_protection.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_branch_protection.go @@ -14,77 +14,78 @@ import ( // BranchProtection represents a branch protection for a repository type BranchProtection struct { - BranchName string `json:"branch_name"` - EnablePush bool `json:"enable_push"` - EnablePushWhitelist bool `json:"enable_push_whitelist"` - PushWhitelistUsernames []string `json:"push_whitelist_usernames"` - PushWhitelistTeams []string `json:"push_whitelist_teams"` - PushWhitelistDeployKeys bool `json:"push_whitelist_deploy_keys"` - EnableMergeWhitelist bool `json:"enable_merge_whitelist"` - MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"` - MergeWhitelistTeams []string `json:"merge_whitelist_teams"` - EnableStatusCheck bool `json:"enable_status_check"` - StatusCheckContexts []string `json:"status_check_contexts"` - RequiredApprovals int64 `json:"required_approvals"` - EnableApprovalsWhitelist bool `json:"enable_approvals_whitelist"` - ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"` - ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"` - BlockOnRejectedReviews bool `json:"block_on_rejected_reviews"` - BlockOnOutdatedBranch bool `json:"block_on_outdated_branch"` - DismissStaleApprovals bool `json:"dismiss_stale_approvals"` - RequireSignedCommits bool `json:"require_signed_commits"` - ProtectedFilePatterns string `json:"protected_file_patterns"` - // swagger:strfmt date-time - Created time.Time `json:"created_at"` - // swagger:strfmt date-time - Updated time.Time `json:"updated_at"` + BranchName string `json:"branch_name"` + EnablePush bool `json:"enable_push"` + EnablePushWhitelist bool `json:"enable_push_whitelist"` + PushWhitelistUsernames []string `json:"push_whitelist_usernames"` + PushWhitelistTeams []string `json:"push_whitelist_teams"` + PushWhitelistDeployKeys bool `json:"push_whitelist_deploy_keys"` + EnableMergeWhitelist bool `json:"enable_merge_whitelist"` + MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"` + MergeWhitelistTeams []string `json:"merge_whitelist_teams"` + EnableStatusCheck bool `json:"enable_status_check"` + StatusCheckContexts []string `json:"status_check_contexts"` + RequiredApprovals int64 `json:"required_approvals"` + EnableApprovalsWhitelist bool `json:"enable_approvals_whitelist"` + ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"` + ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"` + BlockOnRejectedReviews bool `json:"block_on_rejected_reviews"` + BlockOnOfficialReviewRequests bool `json:"block_on_official_review_requests"` + BlockOnOutdatedBranch bool `json:"block_on_outdated_branch"` + DismissStaleApprovals bool `json:"dismiss_stale_approvals"` + RequireSignedCommits bool `json:"require_signed_commits"` + ProtectedFilePatterns string `json:"protected_file_patterns"` + Created time.Time `json:"created_at"` + Updated time.Time `json:"updated_at"` } // CreateBranchProtectionOption options for creating a branch protection type CreateBranchProtectionOption struct { - BranchName string `json:"branch_name"` - EnablePush bool `json:"enable_push"` - EnablePushWhitelist bool `json:"enable_push_whitelist"` - PushWhitelistUsernames []string `json:"push_whitelist_usernames"` - PushWhitelistTeams []string `json:"push_whitelist_teams"` - PushWhitelistDeployKeys bool `json:"push_whitelist_deploy_keys"` - EnableMergeWhitelist bool `json:"enable_merge_whitelist"` - MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"` - MergeWhitelistTeams []string `json:"merge_whitelist_teams"` - EnableStatusCheck bool `json:"enable_status_check"` - StatusCheckContexts []string `json:"status_check_contexts"` - RequiredApprovals int64 `json:"required_approvals"` - EnableApprovalsWhitelist bool `json:"enable_approvals_whitelist"` - ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"` - ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"` - BlockOnRejectedReviews bool `json:"block_on_rejected_reviews"` - BlockOnOutdatedBranch bool `json:"block_on_outdated_branch"` - DismissStaleApprovals bool `json:"dismiss_stale_approvals"` - RequireSignedCommits bool `json:"require_signed_commits"` - ProtectedFilePatterns string `json:"protected_file_patterns"` + BranchName string `json:"branch_name"` + EnablePush bool `json:"enable_push"` + EnablePushWhitelist bool `json:"enable_push_whitelist"` + PushWhitelistUsernames []string `json:"push_whitelist_usernames"` + PushWhitelistTeams []string `json:"push_whitelist_teams"` + PushWhitelistDeployKeys bool `json:"push_whitelist_deploy_keys"` + EnableMergeWhitelist bool `json:"enable_merge_whitelist"` + MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"` + MergeWhitelistTeams []string `json:"merge_whitelist_teams"` + EnableStatusCheck bool `json:"enable_status_check"` + StatusCheckContexts []string `json:"status_check_contexts"` + RequiredApprovals int64 `json:"required_approvals"` + EnableApprovalsWhitelist bool `json:"enable_approvals_whitelist"` + ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"` + ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"` + BlockOnRejectedReviews bool `json:"block_on_rejected_reviews"` + BlockOnOfficialReviewRequests bool `json:"block_on_official_review_requests"` + BlockOnOutdatedBranch bool `json:"block_on_outdated_branch"` + DismissStaleApprovals bool `json:"dismiss_stale_approvals"` + RequireSignedCommits bool `json:"require_signed_commits"` + ProtectedFilePatterns string `json:"protected_file_patterns"` } // EditBranchProtectionOption options for editing a branch protection type EditBranchProtectionOption struct { - EnablePush *bool `json:"enable_push"` - EnablePushWhitelist *bool `json:"enable_push_whitelist"` - PushWhitelistUsernames []string `json:"push_whitelist_usernames"` - PushWhitelistTeams []string `json:"push_whitelist_teams"` - PushWhitelistDeployKeys *bool `json:"push_whitelist_deploy_keys"` - EnableMergeWhitelist *bool `json:"enable_merge_whitelist"` - MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"` - MergeWhitelistTeams []string `json:"merge_whitelist_teams"` - EnableStatusCheck *bool `json:"enable_status_check"` - StatusCheckContexts []string `json:"status_check_contexts"` - RequiredApprovals *int64 `json:"required_approvals"` - EnableApprovalsWhitelist *bool `json:"enable_approvals_whitelist"` - ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"` - ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"` - BlockOnRejectedReviews *bool `json:"block_on_rejected_reviews"` - BlockOnOutdatedBranch *bool `json:"block_on_outdated_branch"` - DismissStaleApprovals *bool `json:"dismiss_stale_approvals"` - RequireSignedCommits *bool `json:"require_signed_commits"` - ProtectedFilePatterns *string `json:"protected_file_patterns"` + EnablePush *bool `json:"enable_push"` + EnablePushWhitelist *bool `json:"enable_push_whitelist"` + PushWhitelistUsernames []string `json:"push_whitelist_usernames"` + PushWhitelistTeams []string `json:"push_whitelist_teams"` + PushWhitelistDeployKeys *bool `json:"push_whitelist_deploy_keys"` + EnableMergeWhitelist *bool `json:"enable_merge_whitelist"` + MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"` + MergeWhitelistTeams []string `json:"merge_whitelist_teams"` + EnableStatusCheck *bool `json:"enable_status_check"` + StatusCheckContexts []string `json:"status_check_contexts"` + RequiredApprovals *int64 `json:"required_approvals"` + EnableApprovalsWhitelist *bool `json:"enable_approvals_whitelist"` + ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"` + ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"` + BlockOnRejectedReviews *bool `json:"block_on_rejected_reviews"` + BlockOnOfficialReviewRequests *bool `json:"block_on_official_review_requests"` + BlockOnOutdatedBranch *bool `json:"block_on_outdated_branch"` + DismissStaleApprovals *bool `json:"dismiss_stale_approvals"` + RequireSignedCommits *bool `json:"require_signed_commits"` + ProtectedFilePatterns *string `json:"protected_file_patterns"` } // ListBranchProtectionsOptions list branch protection options @@ -93,56 +94,60 @@ type ListBranchProtectionsOptions struct { } // ListBranchProtections list branch protections for a repo -func (c *Client) ListBranchProtections(owner, repo string, opt ListBranchProtectionsOptions) ([]*BranchProtection, error) { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return nil, err +func (c *Client) ListBranchProtections(owner, repo string, opt ListBranchProtectionsOptions) ([]*BranchProtection, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, nil, err } - bps := make([]*BranchProtection, 0, 5) + bps := make([]*BranchProtection, 0, opt.PageSize) link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/branch_protections", owner, repo)) link.RawQuery = opt.getURLQuery().Encode() - return bps, c.getParsedResponse("GET", link.String(), jsonHeader, nil, &bps) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &bps) + return bps, resp, err } // GetBranchProtection gets a branch protection -func (c *Client) GetBranchProtection(owner, repo, name string) (*BranchProtection, error) { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return nil, err +func (c *Client) GetBranchProtection(owner, repo, name string) (*BranchProtection, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, nil, err } bp := new(BranchProtection) - return bp, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, nil, bp) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, nil, bp) + return bp, resp, err } // CreateBranchProtection creates a branch protection for a repo -func (c *Client) CreateBranchProtection(owner, repo string, opt CreateBranchProtectionOption) (*BranchProtection, error) { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return nil, err +func (c *Client) CreateBranchProtection(owner, repo string, opt CreateBranchProtectionOption) (*BranchProtection, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, nil, err } bp := new(BranchProtection) body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } - return bp, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/branch_protections", owner, repo), jsonHeader, bytes.NewReader(body), bp) + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/branch_protections", owner, repo), jsonHeader, bytes.NewReader(body), bp) + return bp, resp, err } // EditBranchProtection edits a branch protection for a repo -func (c *Client) EditBranchProtection(owner, repo, name string, opt EditBranchProtectionOption) (*BranchProtection, error) { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return nil, err +func (c *Client) EditBranchProtection(owner, repo, name string, opt EditBranchProtectionOption) (*BranchProtection, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, nil, err } bp := new(BranchProtection) body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } - return bp, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, bytes.NewReader(body), bp) + resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, bytes.NewReader(body), bp) + return bp, resp, err } // DeleteBranchProtection deletes a branch protection for a repo -func (c *Client) DeleteBranchProtection(owner, repo, name string) error { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return err +func (c *Client) DeleteBranchProtection(owner, repo, name string) (*Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, err } - _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, nil) - return err + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/repo_collaborator.go b/vendor/code.gitea.io/sdk/gitea/repo_collaborator.go index e13ccdbd3..63c4eafd5 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_collaborator.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_collaborator.go @@ -16,44 +16,82 @@ type ListCollaboratorsOptions struct { } // ListCollaborators list a repository's collaborators -func (c *Client) ListCollaborators(user, repo string, opt ListCollaboratorsOptions) ([]*User, error) { +func (c *Client) ListCollaborators(user, repo string, opt ListCollaboratorsOptions) ([]*User, *Response, error) { opt.setDefaults() collaborators := make([]*User, 0, opt.PageSize) - return collaborators, c.getParsedResponse("GET", + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/collaborators?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &collaborators) + return collaborators, resp, err } // IsCollaborator check if a user is a collaborator of a repository -func (c *Client) IsCollaborator(user, repo, collaborator string) (bool, error) { - status, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), nil, nil) +func (c *Client) IsCollaborator(user, repo, collaborator string) (bool, *Response, error) { + status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), nil, nil) if err != nil { - return false, err + return false, resp, err } if status == 204 { - return true, nil + return true, resp, nil } - return false, nil + return false, resp, nil } // AddCollaboratorOption options when adding a user as a collaborator of a repository type AddCollaboratorOption struct { - Permission *string `json:"permission"` + Permission *AccessMode `json:"permission"` +} + +// AccessMode represent the grade of access you have to something +type AccessMode string + +const ( + // AccessModeNone no access + AccessModeNone AccessMode = "none" + // AccessModeRead read access + AccessModeRead AccessMode = "read" + // AccessModeWrite write access + AccessModeWrite AccessMode = "write" + // AccessModeAdmin admin access + AccessModeAdmin AccessMode = "admin" + // AccessModeOwner owner + AccessModeOwner AccessMode = "owner" +) + +// Validate the AddCollaboratorOption struct +func (opt AddCollaboratorOption) Validate() error { + if opt.Permission != nil { + if *opt.Permission == AccessModeOwner { + *opt.Permission = AccessModeAdmin + return nil + } + if *opt.Permission == AccessModeNone { + opt.Permission = nil + return nil + } + if *opt.Permission != AccessModeRead && *opt.Permission != AccessModeWrite && *opt.Permission != AccessModeAdmin { + return fmt.Errorf("permission mode invalid") + } + } + return nil } // AddCollaborator add some user as a collaborator of a repository -func (c *Client) AddCollaborator(user, repo, collaborator string, opt AddCollaboratorOption) error { +func (c *Client) AddCollaborator(user, repo, collaborator string, opt AddCollaboratorOption) (*Response, error) { + if err := opt.Validate(); err != nil { + return nil, err + } body, err := json.Marshal(&opt) if err != nil { - return err + return nil, err } - _, err = c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), jsonHeader, bytes.NewReader(body)) - return err + _, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), jsonHeader, bytes.NewReader(body)) + return resp, err } // DeleteCollaborator remove a collaborator from a repository -func (c *Client) DeleteCollaborator(user, repo, collaborator string) error { - _, err := c.getResponse("DELETE", +func (c *Client) DeleteCollaborator(user, repo, collaborator string) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), nil, nil) - return err + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/repo_commit.go b/vendor/code.gitea.io/sdk/gitea/repo_commit.go index 82ef3fa97..57df8e865 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_commit.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_commit.go @@ -19,8 +19,9 @@ type Identity struct { // CommitMeta contains meta information of a commit in terms of API. type CommitMeta struct { - URL string `json:"url"` - SHA string `json:"sha"` + URL string `json:"url"` + SHA string `json:"sha"` + Created time.Time `json:"created"` } // CommitUser contains information of a user in the context of a commit. @@ -41,11 +42,12 @@ type RepoCommit struct { // Commit contains information generated from a Git commit. type Commit struct { *CommitMeta - HTMLURL string `json:"html_url"` - RepoCommit *RepoCommit `json:"commit"` - Author *User `json:"author"` - Committer *User `json:"committer"` - Parents []*CommitMeta `json:"parents"` + HTMLURL string `json:"html_url"` + RepoCommit *RepoCommit `json:"commit"` + Author *User `json:"author"` + Committer *User `json:"committer"` + Parents []*CommitMeta `json:"parents"` + Files []*CommitAffectedFiles `json:"files"` } // CommitDateOptions store dates for GIT_AUTHOR_DATE and GIT_COMMITTER_DATE @@ -54,10 +56,16 @@ type CommitDateOptions struct { Committer time.Time `json:"committer"` } +// CommitAffectedFiles store information about files affected by the commit +type CommitAffectedFiles struct { + Filename string `json:"filename"` +} + // GetSingleCommit returns a single commit -func (c *Client) GetSingleCommit(user, repo, commitID string) (*Commit, error) { +func (c *Client) GetSingleCommit(user, repo, commitID string) (*Commit, *Response, error) { commit := new(Commit) - return commit, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/commits/%s", user, repo, commitID), nil, nil, &commit) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/commits/%s", user, repo, commitID), nil, nil, &commit) + return commit, resp, err } // ListCommitOptions list commit options @@ -77,10 +85,11 @@ func (opt *ListCommitOptions) QueryEncode() string { } // ListRepoCommits return list of commits from a repo -func (c *Client) ListRepoCommits(user, repo string, opt ListCommitOptions) ([]*Commit, error) { +func (c *Client) ListRepoCommits(user, repo string, opt ListCommitOptions) ([]*Commit, *Response, error) { link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/commits", user, repo)) opt.setDefaults() commits := make([]*Commit, 0, opt.PageSize) link.RawQuery = opt.QueryEncode() - return commits, c.getParsedResponse("GET", link.String(), nil, nil, &commits) + resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &commits) + return commits, resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/repo_file.go b/vendor/code.gitea.io/sdk/gitea/repo_file.go index 18818592d..bebe95c1a 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_file.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_file.go @@ -9,6 +9,8 @@ import ( "bytes" "encoding/json" "fmt" + "net/url" + "strings" ) // FileOptions options for all file APIs @@ -23,6 +25,8 @@ type FileOptions struct { Author Identity `json:"author"` Committer Identity `json:"committer"` Dates CommitDateOptions `json:"dates"` + // Add a Signed-off-by trailer by the committer at the end of the commit log message. + Signoff bool `json:"signoff"` } // CreateFileOptions options for creating files @@ -112,76 +116,121 @@ type FileDeleteResponse struct { Verification *PayloadCommitVerification `json:"verification"` } +// pathEscapeSegments escapes segments of a path while not escaping forward slash +func pathEscapeSegments(path string) string { + slice := strings.Split(path, "/") + for index := range slice { + slice[index] = url.PathEscape(slice[index]) + } + escapedPath := strings.Join(slice, "/") + return escapedPath +} + // GetFile downloads a file of repository, ref can be branch/tag/commit. -// e.g.: ref -> master, tree -> macaron.go(no leading slash) -func (c *Client) GetFile(user, repo, ref, tree string) ([]byte, error) { - return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/raw/%s/%s", user, repo, ref, tree), nil, nil) +// e.g.: ref -> master, filepath -> README.md (no leading slash) +func (c *Client) GetFile(owner, repo, ref, filepath string) ([]byte, *Response, error) { + filepath = pathEscapeSegments(filepath) + if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil { + ref = pathEscapeSegments(ref) + return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/raw/%s/%s", owner, repo, ref, filepath), nil, nil) + } + return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/raw/%s?ref=%s", owner, repo, filepath, url.QueryEscape(ref)), nil, nil) } -// GetContents get the metadata and contents (if a file) of an entry in a repository, or a list of entries if a dir +// GetContents get the metadata and contents of a file in a repository // ref is optional -func (c *Client) GetContents(owner, repo, ref, filepath string) (*ContentsResponse, error) { +func (c *Client) GetContents(owner, repo, ref, filepath string) (*ContentsResponse, *Response, error) { + data, resp, err := c.getDirOrFileContents(owner, repo, ref, filepath) + if err != nil { + return nil, resp, err + } cr := new(ContentsResponse) - return cr, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/contents/%s?ref=%s", owner, repo, filepath, ref), jsonHeader, nil, cr) + if json.Unmarshal(data, &cr) != nil { + return nil, resp, fmt.Errorf("expect file, got directory") + } + return cr, resp, err +} + +// ListContents gets a list of entries in a dir +// ref is optional +func (c *Client) ListContents(owner, repo, ref, filepath string) ([]*ContentsResponse, *Response, error) { + data, resp, err := c.getDirOrFileContents(owner, repo, ref, filepath) + if err != nil { + return nil, resp, err + } + crl := make([]*ContentsResponse, 0) + if json.Unmarshal(data, &crl) != nil { + return nil, resp, fmt.Errorf("expect directory, got file") + } + return crl, resp, err +} +func (c *Client) getDirOrFileContents(owner, repo, ref, filepath string) ([]byte, *Response, error) { + filepath = pathEscapeSegments(strings.TrimPrefix(filepath, "/")) + return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/contents/%s?ref=%s", owner, repo, filepath, url.QueryEscape(ref)), jsonHeader, nil) } // CreateFile create a file in a repository -func (c *Client) CreateFile(owner, repo, filepath string, opt CreateFileOptions) (*FileResponse, error) { +func (c *Client) CreateFile(owner, repo, filepath string, opt CreateFileOptions) (*FileResponse, *Response, error) { + filepath = pathEscapeSegments(filepath) var err error if opt.BranchName, err = c.setDefaultBranchForOldVersions(owner, repo, opt.BranchName); err != nil { - return nil, err + return nil, nil, err } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } fr := new(FileResponse) - return fr, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body), fr) + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body), fr) + return fr, resp, err } // UpdateFile update a file in a repository -func (c *Client) UpdateFile(owner, repo, filepath string, opt UpdateFileOptions) (*FileResponse, error) { +func (c *Client) UpdateFile(owner, repo, filepath string, opt UpdateFileOptions) (*FileResponse, *Response, error) { + filepath = pathEscapeSegments(filepath) var err error if opt.BranchName, err = c.setDefaultBranchForOldVersions(owner, repo, opt.BranchName); err != nil { - return nil, err + return nil, nil, err } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } fr := new(FileResponse) - return fr, c.getParsedResponse("PUT", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body), fr) + resp, err := c.getParsedResponse("PUT", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body), fr) + return fr, resp, err } // DeleteFile delete a file from repository -func (c *Client) DeleteFile(owner, repo, filepath string, opt DeleteFileOptions) error { +func (c *Client) DeleteFile(owner, repo, filepath string, opt DeleteFileOptions) (*Response, error) { + filepath = pathEscapeSegments(filepath) var err error if opt.BranchName, err = c.setDefaultBranchForOldVersions(owner, repo, opt.BranchName); err != nil { - return err + return nil, err } body, err := json.Marshal(&opt) if err != nil { - return err + return nil, err } - status, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body)) + status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body)) if err != nil { - return err + return resp, err } if status != 200 && status != 204 { - return fmt.Errorf("unexpected Status: %d", status) + return resp, fmt.Errorf("unexpected Status: %d", status) } - return nil + return resp, nil } func (c *Client) setDefaultBranchForOldVersions(owner, repo, branch string) (string, error) { if len(branch) == 0 { // Gitea >= 1.12.0 Use DefaultBranch on "", mimic this for older versions - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - r, err := c.GetRepo(owner, repo) + if c.checkServerVersionGreaterThanOrEqual(version1_12_0) != nil { + r, _, err := c.GetRepo(owner, repo) if err != nil { return "", err } diff --git a/vendor/code.gitea.io/sdk/gitea/repo_key.go b/vendor/code.gitea.io/sdk/gitea/repo_key.go index 041df5da8..cfdfe0cd4 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_key.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_key.go @@ -45,32 +45,35 @@ func (opt *ListDeployKeysOptions) QueryEncode() string { } // ListDeployKeys list all the deploy keys of one repository -func (c *Client) ListDeployKeys(user, repo string, opt ListDeployKeysOptions) ([]*DeployKey, error) { +func (c *Client) ListDeployKeys(user, repo string, opt ListDeployKeysOptions) ([]*DeployKey, *Response, error) { link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/keys", user, repo)) opt.setDefaults() link.RawQuery = opt.QueryEncode() keys := make([]*DeployKey, 0, opt.PageSize) - return keys, c.getParsedResponse("GET", link.String(), nil, nil, &keys) + resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &keys) + return keys, resp, err } // GetDeployKey get one deploy key with key id -func (c *Client) GetDeployKey(user, repo string, keyID int64) (*DeployKey, error) { +func (c *Client) GetDeployKey(user, repo string, keyID int64) (*DeployKey, *Response, error) { key := new(DeployKey) - return key, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/keys/%d", user, repo, keyID), nil, nil, &key) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/keys/%d", user, repo, keyID), nil, nil, &key) + return key, resp, err } // CreateDeployKey options when create one deploy key -func (c *Client) CreateDeployKey(user, repo string, opt CreateKeyOption) (*DeployKey, error) { +func (c *Client) CreateDeployKey(user, repo string, opt CreateKeyOption) (*DeployKey, *Response, error) { body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } key := new(DeployKey) - return key, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/keys", user, repo), jsonHeader, bytes.NewReader(body), key) + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/keys", user, repo), jsonHeader, bytes.NewReader(body), key) + return key, resp, err } // DeleteDeployKey delete deploy key with key id -func (c *Client) DeleteDeployKey(owner, repo string, keyID int64) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/keys/%d", owner, repo, keyID), nil, nil) - return err +func (c *Client) DeleteDeployKey(owner, repo string, keyID int64) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/keys/%d", owner, repo, keyID), nil, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/repo_migrate.go b/vendor/code.gitea.io/sdk/gitea/repo_migrate.go new file mode 100644 index 000000000..91f19d6ae --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/repo_migrate.go @@ -0,0 +1,130 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "bytes" + "encoding/json" + "fmt" +) + +// GitServiceType represents a git service +type GitServiceType string + +const ( + // GitServicePlain represents a plain git service + GitServicePlain GitServiceType = "git" + //GitServiceGithub represents github.com + GitServiceGithub GitServiceType = "github" + // GitServiceGitlab represents a gitlab service + GitServiceGitlab GitServiceType = "gitlab" + // GitServiceGitea represents a gitea service + GitServiceGitea GitServiceType = "gitea" + // GitServiceGogs represents a gogs service + GitServiceGogs GitServiceType = "gogs" +) + +// MigrateRepoOption options for migrating a repository from an external service +type MigrateRepoOption struct { + RepoName string `json:"repo_name"` + RepoOwner string `json:"repo_owner"` + // deprecated use RepoOwner + RepoOwnerID int64 `json:"uid"` + CloneAddr string `json:"clone_addr"` + Service GitServiceType `json:"service"` + AuthUsername string `json:"auth_username"` + AuthPassword string `json:"auth_password"` + AuthToken string `json:"auth_token"` + Mirror bool `json:"mirror"` + Private bool `json:"private"` + Description string `json:"description"` + Wiki bool `json:"wiki"` + Milestones bool `json:"milestones"` + Labels bool `json:"labels"` + Issues bool `json:"issues"` + PullRequests bool `json:"pull_requests"` + Releases bool `json:"releases"` + MirrorInterval string `json:"mirror_interval"` +} + +// Validate the MigrateRepoOption struct +func (opt *MigrateRepoOption) Validate(c *Client) error { + // check user options + if len(opt.CloneAddr) == 0 { + return fmt.Errorf("CloneAddr required") + } + if len(opt.RepoName) == 0 { + return fmt.Errorf("RepoName required") + } else if len(opt.RepoName) > 100 { + return fmt.Errorf("RepoName to long") + } + if len(opt.Description) > 255 { + return fmt.Errorf("Description to long") + } + switch opt.Service { + case GitServiceGithub: + if len(opt.AuthToken) == 0 { + return fmt.Errorf("github requires token authentication") + } + case GitServiceGitlab, GitServiceGitea: + if len(opt.AuthToken) == 0 { + return fmt.Errorf("%s requires token authentication", opt.Service) + } + // Gitlab is supported since 1.12.0 but api cant handle it until 1.13.0 + // https://github.com/go-gitea/gitea/pull/12672 + if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil { + return fmt.Errorf("migrate from service %s need gitea >= 1.13.0", opt.Service) + } + case GitServiceGogs: + if len(opt.AuthToken) == 0 { + return fmt.Errorf("gogs requires token authentication") + } + if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil { + return fmt.Errorf("migrate from service gogs need gitea >= 1.14.0") + } + } + return nil +} + +// MigrateRepo migrates a repository from other Git hosting sources for the authenticated user. +// +// To migrate a repository for a organization, the authenticated user must be a +// owner of the specified organization. +func (c *Client) MigrateRepo(opt MigrateRepoOption) (*Repository, *Response, error) { + if err := opt.Validate(c); err != nil { + return nil, nil, err + } + + if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil { + if len(opt.AuthToken) != 0 { + // gitea <= 1.12 dont understand AuthToken + opt.AuthUsername = opt.AuthToken + opt.AuthPassword, opt.AuthToken = "", "" + } + if len(opt.RepoOwner) != 0 { + // gitea <= 1.12 dont understand RepoOwner + u, _, err := c.GetUserInfo(opt.RepoOwner) + if err != nil { + return nil, nil, err + } + opt.RepoOwnerID = u.ID + } else if opt.RepoOwnerID == 0 { + // gitea <= 1.12 require RepoOwnerID + u, _, err := c.GetMyUserInfo() + if err != nil { + return nil, nil, err + } + opt.RepoOwnerID = u.ID + } + } + + body, err := json.Marshal(&opt) + if err != nil { + return nil, nil, err + } + repo := new(Repository) + resp, err := c.getParsedResponse("POST", "/repos/migrate", jsonHeader, bytes.NewReader(body), repo) + return repo, resp, err +} diff --git a/vendor/code.gitea.io/sdk/gitea/repo_refs.go b/vendor/code.gitea.io/sdk/gitea/repo_refs.go index b946a1002..fa1698a49 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_refs.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_refs.go @@ -26,44 +26,44 @@ type GitObject struct { } // GetRepoRef get one ref's information of one repository -func (c *Client) GetRepoRef(user, repo, ref string) (*Reference, error) { +func (c *Client) GetRepoRef(user, repo, ref string) (*Reference, *Response, error) { ref = strings.TrimPrefix(ref, "refs/") r := new(Reference) - err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/refs/%s", user, repo, ref), nil, nil, &r) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/refs/%s", user, repo, ref), nil, nil, &r) if _, ok := err.(*json.UnmarshalTypeError); ok { // Multiple refs - return nil, errors.New("no exact match found for this ref") + return nil, resp, errors.New("no exact match found for this ref") } else if err != nil { - return nil, err + return nil, resp, err } - return r, nil + return r, resp, nil } // GetRepoRefs get list of ref's information of one repository -func (c *Client) GetRepoRefs(user, repo, ref string) ([]*Reference, error) { +func (c *Client) GetRepoRefs(user, repo, ref string) ([]*Reference, *Response, error) { ref = strings.TrimPrefix(ref, "refs/") - resp, err := c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/git/refs/%s", user, repo, ref), nil, nil) + data, resp, err := c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/git/refs/%s", user, repo, ref), nil, nil) if err != nil { - return nil, err + return nil, resp, err } // Attempt to unmarshal single returned ref. r := new(Reference) - refErr := json.Unmarshal(resp, r) + refErr := json.Unmarshal(data, r) if refErr == nil { - return []*Reference{r}, nil + return []*Reference{r}, resp, nil } // Attempt to unmarshal multiple refs. var rs []*Reference - refsErr := json.Unmarshal(resp, &rs) + refsErr := json.Unmarshal(data, &rs) if refsErr == nil { if len(rs) == 0 { - return nil, errors.New("unexpected response: an array of refs with length 0") + return nil, resp, errors.New("unexpected response: an array of refs with length 0") } - return rs, nil + return rs, resp, nil } - return nil, fmt.Errorf("unmarshalling failed for both single and multiple refs: %s and %s", refErr, refsErr) + return nil, resp, fmt.Errorf("unmarshalling failed for both single and multiple refs: %s and %s", refErr, refsErr) } diff --git a/vendor/code.gitea.io/sdk/gitea/repo_stars.go b/vendor/code.gitea.io/sdk/gitea/repo_stars.go new file mode 100644 index 000000000..b4bd981f4 --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/repo_stars.go @@ -0,0 +1,81 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "fmt" + "net/http" +) + +// ListStargazersOptions options for listing a repository's stargazers +type ListStargazersOptions struct { + ListOptions +} + +// ListRepoStargazers list a repository's stargazers +func (c *Client) ListRepoStargazers(user, repo string, opt ListStargazersOptions) ([]*User, *Response, error) { + opt.setDefaults() + stargazers := make([]*User, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/stargazers?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &stargazers) + return stargazers, resp, err +} + +// GetStarredRepos returns the repos that the given user has starred +func (c *Client) GetStarredRepos(user string) ([]*Repository, *Response, error) { + repos := make([]*Repository, 0, 10) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/starred", user), jsonHeader, nil, &repos) + return repos, resp, err +} + +// GetMyStarredRepos returns the repos that the authenticated user has starred +func (c *Client) GetMyStarredRepos() ([]*Repository, *Response, error) { + repos := make([]*Repository, 0, 10) + resp, err := c.getParsedResponse("GET", "/user/starred", jsonHeader, nil, &repos) + return repos, resp, err +} + +// IsRepoStarring returns whether the authenticated user has starred the repo or not +func (c *Client) IsRepoStarring(user, repo string) (bool, *Response, error) { + _, resp, err := c.getResponse("GET", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil) + if resp != nil { + switch resp.StatusCode { + case http.StatusNotFound: + return false, resp, nil + case http.StatusNoContent: + return true, resp, nil + default: + return false, resp, fmt.Errorf("unexpected status code '%d'", resp.StatusCode) + } + } + return false, nil, err +} + +// StarRepo star specified repo as the authenticated user +func (c *Client) StarRepo(user, repo string) (*Response, error) { + _, resp, err := c.getResponse("PUT", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil) + if resp != nil { + switch resp.StatusCode { + case http.StatusNoContent: + return resp, nil + default: + return resp, fmt.Errorf("unexpected status code '%d'", resp.StatusCode) + } + } + return nil, err +} + +// UnStarRepo remove star to specified repo as the authenticated user +func (c *Client) UnStarRepo(user, repo string) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil) + if resp != nil { + switch resp.StatusCode { + case http.StatusNoContent: + return resp, nil + default: + return resp, fmt.Errorf("unexpected status code '%d'", resp.StatusCode) + } + } + return nil, err +} diff --git a/vendor/code.gitea.io/sdk/gitea/repo_tag.go b/vendor/code.gitea.io/sdk/gitea/repo_tag.go index b64d90b81..6565fa701 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_tag.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_tag.go @@ -23,8 +23,20 @@ type ListRepoTagsOptions struct { } // ListRepoTags list all the branches of one repository -func (c *Client) ListRepoTags(user, repo string, opt ListRepoTagsOptions) ([]*Tag, error) { +func (c *Client) ListRepoTags(user, repo string, opt ListRepoTagsOptions) ([]*Tag, *Response, error) { opt.setDefaults() tags := make([]*Tag, 0, opt.PageSize) - return tags, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/tags?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &tags) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/tags?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &tags) + return tags, resp, err +} + +// DeleteTag deletes a tag from a repository, if no release refers to it +func (c *Client) DeleteTag(user, repo string, tag string) (*Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil { + return nil, err + } + _, resp, err := c.getResponse("DELETE", + fmt.Sprintf("/repos/%s/%s/tags/%s", user, repo, tag), + nil, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/repo_topics.go b/vendor/code.gitea.io/sdk/gitea/repo_topics.go index 8d90e2691..fd05d0899 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_topics.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_topics.go @@ -21,38 +21,38 @@ type topicsList struct { } // ListRepoTopics list all repository's topics -func (c *Client) ListRepoTopics(user, repo string, opt ListRepoTopicsOptions) ([]string, error) { +func (c *Client) ListRepoTopics(user, repo string, opt ListRepoTopicsOptions) ([]string, *Response, error) { opt.setDefaults() list := new(topicsList) - err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/topics?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, list) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/topics?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, list) if err != nil { - return nil, err + return nil, resp, err } - return list.Topics, nil + return list.Topics, resp, nil } // SetRepoTopics replaces the list of repo's topics -func (c *Client) SetRepoTopics(user, repo string, list []string) error { +func (c *Client) SetRepoTopics(user, repo string, list []string) (*Response, error) { l := topicsList{Topics: list} body, err := json.Marshal(&l) if err != nil { - return err + return nil, err } - _, err = c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/topics", user, repo), jsonHeader, bytes.NewReader(body)) - return err + _, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/topics", user, repo), jsonHeader, bytes.NewReader(body)) + return resp, err } // AddRepoTopic adds a topic to a repo's topics list -func (c *Client) AddRepoTopic(user, repo, topic string) error { - _, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/topics/%s", user, repo, topic), nil, nil) - return err +func (c *Client) AddRepoTopic(user, repo, topic string) (*Response, error) { + _, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/topics/%s", user, repo, topic), nil, nil) + return resp, err } // DeleteRepoTopic deletes a topic from repo's topics list -func (c *Client) DeleteRepoTopic(user, repo, topic string) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/topics/%s", user, repo, topic), nil, nil) - return err +func (c *Client) DeleteRepoTopic(user, repo, topic string) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/topics/%s", user, repo, topic), nil, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/repo_transfer.go b/vendor/code.gitea.io/sdk/gitea/repo_transfer.go index 1b61e2f38..d8d661bc4 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_transfer.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_transfer.go @@ -19,14 +19,15 @@ type TransferRepoOption struct { } // TransferRepo transfers the ownership of a repository -func (c *Client) TransferRepo(owner, reponame string, opt TransferRepoOption) (*Repository, error) { - if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil { - return nil, err +func (c *Client) TransferRepo(owner, reponame string, opt TransferRepoOption) (*Repository, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + return nil, nil, err } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } repo := new(Repository) - return repo, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/transfer", owner, reponame), jsonHeader, bytes.NewReader(body), repo) + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/transfer", owner, reponame), jsonHeader, bytes.NewReader(body), repo) + return repo, resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/repo_tree.go b/vendor/code.gitea.io/sdk/gitea/repo_tree.go index d258bdfff..ce36e460b 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_tree.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_tree.go @@ -30,11 +30,12 @@ type GitTreeResponse struct { // GetTrees downloads a file of repository, ref can be branch/tag/commit. // e.g.: ref -> master, tree -> macaron.go(no leading slash) -func (c *Client) GetTrees(user, repo, ref string, recursive bool) (*GitTreeResponse, error) { +func (c *Client) GetTrees(user, repo, ref string, recursive bool) (*GitTreeResponse, *Response, error) { trees := new(GitTreeResponse) var path = fmt.Sprintf("/repos/%s/%s/git/trees/%s", user, repo, ref) if recursive { path += "?recursive=1" } - return trees, c.getParsedResponse("GET", path, nil, nil, trees) + resp, err := c.getParsedResponse("GET", path, nil, nil, trees) + return trees, resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/repo_watch.go b/vendor/code.gitea.io/sdk/gitea/repo_watch.go index c8ed3a198..7358705fe 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_watch.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_watch.go @@ -21,53 +21,55 @@ type WatchInfo struct { } // GetWatchedRepos list all the watched repos of user -func (c *Client) GetWatchedRepos(user string) ([]*Repository, error) { +func (c *Client) GetWatchedRepos(user string) ([]*Repository, *Response, error) { repos := make([]*Repository, 0, 10) - return repos, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/subscriptions", user), nil, nil, &repos) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/subscriptions", user), nil, nil, &repos) + return repos, resp, err } // GetMyWatchedRepos list repositories watched by the authenticated user -func (c *Client) GetMyWatchedRepos() ([]*Repository, error) { +func (c *Client) GetMyWatchedRepos() ([]*Repository, *Response, error) { repos := make([]*Repository, 0, 10) - return repos, c.getParsedResponse("GET", fmt.Sprintf("/user/subscriptions"), nil, nil, &repos) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/subscriptions"), nil, nil, &repos) + return repos, resp, err } // CheckRepoWatch check if the current user is watching a repo -func (c *Client) CheckRepoWatch(repoUser, repoName string) (bool, error) { - status, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/subscription", repoUser, repoName), nil, nil) +func (c *Client) CheckRepoWatch(repoUser, repoName string) (bool, *Response, error) { + status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/subscription", repoUser, repoName), nil, nil) if err != nil { - return false, err + return false, resp, err } switch status { case http.StatusNotFound: - return false, nil + return false, resp, nil case http.StatusOK: - return true, nil + return true, resp, nil default: - return false, fmt.Errorf("unexpected Status: %d", status) + return false, resp, fmt.Errorf("unexpected Status: %d", status) } } // WatchRepo start to watch a repository -func (c *Client) WatchRepo(repoUser, repoName string) error { - status, err := c.getStatusCode("PUT", fmt.Sprintf("/repos/%s/%s/subscription", repoUser, repoName), nil, nil) +func (c *Client) WatchRepo(repoUser, repoName string) (*Response, error) { + status, resp, err := c.getStatusCode("PUT", fmt.Sprintf("/repos/%s/%s/subscription", repoUser, repoName), nil, nil) if err != nil { - return err + return resp, err } if status == http.StatusOK { - return nil + return resp, nil } - return fmt.Errorf("unexpected Status: %d", status) + return resp, fmt.Errorf("unexpected Status: %d", status) } // UnWatchRepo stop to watch a repository -func (c *Client) UnWatchRepo(repoUser, repoName string) error { - status, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/subscription", repoUser, repoName), nil, nil) +func (c *Client) UnWatchRepo(repoUser, repoName string) (*Response, error) { + status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/subscription", repoUser, repoName), nil, nil) if err != nil { - return err + return resp, err } if status == http.StatusNoContent { - return nil + return resp, nil } - return fmt.Errorf("unexpected Status: %d", status) + return resp, fmt.Errorf("unexpected Status: %d", status) } diff --git a/vendor/code.gitea.io/sdk/gitea/settings.go b/vendor/code.gitea.io/sdk/gitea/settings.go new file mode 100644 index 000000000..134d2ad99 --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/settings.go @@ -0,0 +1,74 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +// GlobalUISettings represent the global ui settings of a gitea instance witch is exposed by API +type GlobalUISettings struct { + DefaultTheme string `json:"default_theme"` + AllowedReactions []string `json:"allowed_reactions"` +} + +// GlobalRepoSettings represent the global repository settings of a gitea instance witch is exposed by API +type GlobalRepoSettings struct { + MirrorsDisabled bool `json:"mirrors_disabled"` + HTTPGitDisabled bool `json:"http_git_disabled"` + MigrationsDisabled bool `json:"migrations_disabled"` +} + +// GlobalAPISettings contains global api settings exposed by it +type GlobalAPISettings struct { + MaxResponseItems int `json:"max_response_items"` + DefaultPagingNum int `json:"default_paging_num"` + DefaultGitTreesPerPage int `json:"default_git_trees_per_page"` + DefaultMaxBlobSize int64 `json:"default_max_blob_size"` +} + +// GlobalAttachmentSettings contains global Attachment settings exposed by API +type GlobalAttachmentSettings struct { + Enabled bool `json:"enabled"` + AllowedTypes string `json:"allowed_types"` + MaxSize int64 `json:"max_size"` + MaxFiles int `json:"max_files"` +} + +// GetGlobalUISettings get global ui settings witch are exposed by API +func (c *Client) GetGlobalUISettings() (*GlobalUISettings, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil { + return nil, nil, err + } + conf := new(GlobalUISettings) + resp, err := c.getParsedResponse("GET", "/settings/ui", jsonHeader, nil, &conf) + return conf, resp, err +} + +// GetGlobalRepoSettings get global repository settings witch are exposed by API +func (c *Client) GetGlobalRepoSettings() (*GlobalRepoSettings, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil { + return nil, nil, err + } + conf := new(GlobalRepoSettings) + resp, err := c.getParsedResponse("GET", "/settings/repository", jsonHeader, nil, &conf) + return conf, resp, err +} + +// GetGlobalAPISettings get global api settings witch are exposed by it +func (c *Client) GetGlobalAPISettings() (*GlobalAPISettings, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil { + return nil, nil, err + } + conf := new(GlobalAPISettings) + resp, err := c.getParsedResponse("GET", "/settings/api", jsonHeader, nil, &conf) + return conf, resp, err +} + +// GetGlobalAttachmentSettings get global repository settings witch are exposed by API +func (c *Client) GetGlobalAttachmentSettings() (*GlobalAttachmentSettings, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil { + return nil, nil, err + } + conf := new(GlobalAttachmentSettings) + resp, err := c.getParsedResponse("GET", "/settings/attachment", jsonHeader, nil, &conf) + return conf, resp, err +} diff --git a/vendor/code.gitea.io/sdk/gitea/status.go b/vendor/code.gitea.io/sdk/gitea/status.go index f072cf89d..be436555a 100644 --- a/vendor/code.gitea.io/sdk/gitea/status.go +++ b/vendor/code.gitea.io/sdk/gitea/status.go @@ -50,13 +50,14 @@ type CreateStatusOption struct { } // CreateStatus creates a new Status for a given Commit -func (c *Client) CreateStatus(owner, repo, sha string, opts CreateStatusOption) (*Status, error) { +func (c *Client) CreateStatus(owner, repo, sha string, opts CreateStatusOption) (*Status, *Response, error) { body, err := json.Marshal(&opts) if err != nil { - return nil, err + return nil, nil, err } status := new(Status) - return status, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/statuses/%s", owner, repo, sha), jsonHeader, bytes.NewReader(body), status) + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/statuses/%s", owner, repo, sha), jsonHeader, bytes.NewReader(body), status) + return status, resp, err } // ListStatusesOption options for listing a repository's commit's statuses @@ -64,11 +65,12 @@ type ListStatusesOption struct { ListOptions } -// ListStatuses returns all statuses for a given Commit -func (c *Client) ListStatuses(owner, repo, sha string, opt ListStatusesOption) ([]*Status, error) { +// ListStatuses returns all statuses for a given Commit by ref +func (c *Client) ListStatuses(owner, repo, ref string, opt ListStatusesOption) ([]*Status, *Response, error) { opt.setDefaults() statuses := make([]*Status, 0, opt.PageSize) - return statuses, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s/statuses?%s", owner, repo, sha, opt.getURLQuery().Encode()), nil, nil, &statuses) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s/statuses?%s", owner, repo, ref, opt.getURLQuery().Encode()), jsonHeader, nil, &statuses) + return statuses, resp, err } // CombinedStatus holds the combined state of several statuses for a single commit @@ -83,7 +85,14 @@ type CombinedStatus struct { } // GetCombinedStatus returns the CombinedStatus for a given Commit -func (c *Client) GetCombinedStatus(owner, repo, sha string) (*CombinedStatus, error) { +func (c *Client) GetCombinedStatus(owner, repo, ref string) (*CombinedStatus, *Response, error) { status := new(CombinedStatus) - return status, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s/status", owner, repo, sha), nil, nil, status) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s/status", owner, repo, ref), jsonHeader, nil, status) + + // gitea api return empty body if nothing here jet + if resp != nil && resp.StatusCode == 200 && err != nil { + return status, resp, nil + } + + return status, resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/user.go b/vendor/code.gitea.io/sdk/gitea/user.go index 243347436..e909c6861 100644 --- a/vendor/code.gitea.io/sdk/gitea/user.go +++ b/vendor/code.gitea.io/sdk/gitea/user.go @@ -29,15 +29,15 @@ type User struct { } // GetUserInfo get user info by user's name -func (c *Client) GetUserInfo(user string) (*User, error) { +func (c *Client) GetUserInfo(user string) (*User, *Response, error) { u := new(User) - err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s", user), nil, nil, u) - return u, err + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s", user), nil, nil, u) + return u, resp, err } // GetMyUserInfo get user info of current user -func (c *Client) GetMyUserInfo() (*User, error) { +func (c *Client) GetMyUserInfo() (*User, *Response, error) { u := new(User) - err := c.getParsedResponse("GET", "/user", nil, nil, u) - return u, err + resp, err := c.getParsedResponse("GET", "/user", nil, nil, u) + return u, resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/user_app.go b/vendor/code.gitea.io/sdk/gitea/user_app.go index 2205371e6..7f7696dc4 100644 --- a/vendor/code.gitea.io/sdk/gitea/user_app.go +++ b/vendor/code.gitea.io/sdk/gitea/user_app.go @@ -9,6 +9,7 @@ import ( "bytes" "encoding/json" "fmt" + "reflect" ) // AccessToken represents an API access token. @@ -25,13 +26,14 @@ type ListAccessTokensOptions struct { } // ListAccessTokens lists all the access tokens of user -func (c *Client) ListAccessTokens(opts ListAccessTokensOptions) ([]*AccessToken, error) { +func (c *Client) ListAccessTokens(opts ListAccessTokensOptions) ([]*AccessToken, *Response, error) { if len(c.username) == 0 { - return nil, fmt.Errorf("\"username\" not set: only BasicAuth allowed") + return nil, nil, fmt.Errorf("\"username\" not set: only BasicAuth allowed") } opts.setDefaults() tokens := make([]*AccessToken, 0, opts.PageSize) - return tokens, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/tokens?%s", c.username, opts.getURLQuery().Encode()), jsonHeader, nil, &tokens) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/tokens?%s", c.username, opts.getURLQuery().Encode()), jsonHeader, nil, &tokens) + return tokens, resp, err } // CreateAccessTokenOption options when create access token @@ -40,23 +42,39 @@ type CreateAccessTokenOption struct { } // CreateAccessToken create one access token with options -func (c *Client) CreateAccessToken(opt CreateAccessTokenOption) (*AccessToken, error) { +func (c *Client) CreateAccessToken(opt CreateAccessTokenOption) (*AccessToken, *Response, error) { if len(c.username) == 0 { - return nil, fmt.Errorf("\"username\" not set: only BasicAuth allowed") + return nil, nil, fmt.Errorf("\"username\" not set: only BasicAuth allowed") } body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } t := new(AccessToken) - return t, c.getParsedResponse("POST", fmt.Sprintf("/users/%s/tokens", c.username), jsonHeader, bytes.NewReader(body), t) + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/users/%s/tokens", c.username), jsonHeader, bytes.NewReader(body), t) + return t, resp, err } -// DeleteAccessToken delete token with key id -func (c *Client) DeleteAccessToken(keyID int64) error { +// DeleteAccessToken delete token, identified by ID and if not available by name +func (c *Client) DeleteAccessToken(value interface{}) (*Response, error) { if len(c.username) == 0 { - return fmt.Errorf("\"username\" not set: only BasicAuth allowed") + return nil, fmt.Errorf("\"username\" not set: only BasicAuth allowed") } - _, err := c.getResponse("DELETE", fmt.Sprintf("/users/%s/tokens/%d", c.username, keyID), jsonHeader, nil) - return err + + var token = "" + + switch reflect.ValueOf(value).Kind() { + case reflect.Int64: + token = fmt.Sprintf("%d", value.(int64)) + case reflect.String: + if err := c.CheckServerVersionConstraint(">= 1.13.0"); err != nil { + return nil, err + } + token = value.(string) + default: + return nil, fmt.Errorf("only string and int64 supported") + } + + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/users/%s/tokens/%s", c.username, token), jsonHeader, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/user_email.go b/vendor/code.gitea.io/sdk/gitea/user_email.go index 5cb4721f6..4962b082b 100644 --- a/vendor/code.gitea.io/sdk/gitea/user_email.go +++ b/vendor/code.gitea.io/sdk/gitea/user_email.go @@ -23,10 +23,11 @@ type ListEmailsOptions struct { } // ListEmails all the email addresses of user -func (c *Client) ListEmails(opt ListEmailsOptions) ([]*Email, error) { +func (c *Client) ListEmails(opt ListEmailsOptions) ([]*Email, *Response, error) { opt.setDefaults() emails := make([]*Email, 0, opt.PageSize) - return emails, c.getParsedResponse("GET", fmt.Sprintf("/user/emails?%s", opt.getURLQuery().Encode()), nil, nil, &emails) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/emails?%s", opt.getURLQuery().Encode()), nil, nil, &emails) + return emails, resp, err } // CreateEmailOption options when creating email addresses @@ -36,13 +37,14 @@ type CreateEmailOption struct { } // AddEmail add one email to current user with options -func (c *Client) AddEmail(opt CreateEmailOption) ([]*Email, error) { +func (c *Client) AddEmail(opt CreateEmailOption) ([]*Email, *Response, error) { body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } emails := make([]*Email, 0, 3) - return emails, c.getParsedResponse("POST", "/user/emails", jsonHeader, bytes.NewReader(body), &emails) + resp, err := c.getParsedResponse("POST", "/user/emails", jsonHeader, bytes.NewReader(body), &emails) + return emails, resp, err } // DeleteEmailOption options when deleting email addresses @@ -52,11 +54,11 @@ type DeleteEmailOption struct { } // DeleteEmail delete one email of current users' -func (c *Client) DeleteEmail(opt DeleteEmailOption) error { +func (c *Client) DeleteEmail(opt DeleteEmailOption) (*Response, error) { body, err := json.Marshal(&opt) if err != nil { - return err + return nil, err } - _, err = c.getResponse("DELETE", "/user/emails", jsonHeader, bytes.NewReader(body)) - return err + _, resp, err := c.getResponse("DELETE", "/user/emails", jsonHeader, bytes.NewReader(body)) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/user_follow.go b/vendor/code.gitea.io/sdk/gitea/user_follow.go index fdc53eff8..c8bafc01e 100644 --- a/vendor/code.gitea.io/sdk/gitea/user_follow.go +++ b/vendor/code.gitea.io/sdk/gitea/user_follow.go @@ -12,17 +12,19 @@ type ListFollowersOptions struct { } // ListMyFollowers list all the followers of current user -func (c *Client) ListMyFollowers(opt ListFollowersOptions) ([]*User, error) { +func (c *Client) ListMyFollowers(opt ListFollowersOptions) ([]*User, *Response, error) { opt.setDefaults() users := make([]*User, 0, opt.PageSize) - return users, c.getParsedResponse("GET", fmt.Sprintf("/user/followers?%s", opt.getURLQuery().Encode()), nil, nil, &users) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/followers?%s", opt.getURLQuery().Encode()), nil, nil, &users) + return users, resp, err } // ListFollowers list all the followers of one user -func (c *Client) ListFollowers(user string, opt ListFollowersOptions) ([]*User, error) { +func (c *Client) ListFollowers(user string, opt ListFollowersOptions) ([]*User, *Response, error) { opt.setDefaults() users := make([]*User, 0, opt.PageSize) - return users, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/followers?%s", user, opt.getURLQuery().Encode()), nil, nil, &users) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/followers?%s", user, opt.getURLQuery().Encode()), nil, nil, &users) + return users, resp, err } // ListFollowingOptions options for listing a user's users being followed @@ -31,39 +33,41 @@ type ListFollowingOptions struct { } // ListMyFollowing list all the users current user followed -func (c *Client) ListMyFollowing(opt ListFollowingOptions) ([]*User, error) { +func (c *Client) ListMyFollowing(opt ListFollowingOptions) ([]*User, *Response, error) { opt.setDefaults() users := make([]*User, 0, opt.PageSize) - return users, c.getParsedResponse("GET", fmt.Sprintf("/user/following?%s", opt.getURLQuery().Encode()), nil, nil, &users) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/following?%s", opt.getURLQuery().Encode()), nil, nil, &users) + return users, resp, err } // ListFollowing list all the users the user followed -func (c *Client) ListFollowing(user string, opt ListFollowingOptions) ([]*User, error) { +func (c *Client) ListFollowing(user string, opt ListFollowingOptions) ([]*User, *Response, error) { opt.setDefaults() users := make([]*User, 0, opt.PageSize) - return users, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/following?%s", user, opt.getURLQuery().Encode()), nil, nil, &users) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/following?%s", user, opt.getURLQuery().Encode()), nil, nil, &users) + return users, resp, err } // IsFollowing if current user followed the target -func (c *Client) IsFollowing(target string) bool { - _, err := c.getResponse("GET", fmt.Sprintf("/user/following/%s", target), nil, nil) - return err == nil +func (c *Client) IsFollowing(target string) (bool, *Response) { + _, resp, err := c.getResponse("GET", fmt.Sprintf("/user/following/%s", target), nil, nil) + return err == nil, resp } // IsUserFollowing if the user followed the target -func (c *Client) IsUserFollowing(user, target string) bool { - _, err := c.getResponse("GET", fmt.Sprintf("/users/%s/following/%s", user, target), nil, nil) - return err == nil +func (c *Client) IsUserFollowing(user, target string) (bool, *Response) { + _, resp, err := c.getResponse("GET", fmt.Sprintf("/users/%s/following/%s", user, target), nil, nil) + return err == nil, resp } // Follow set current user follow the target -func (c *Client) Follow(target string) error { - _, err := c.getResponse("PUT", fmt.Sprintf("/user/following/%s", target), nil, nil) - return err +func (c *Client) Follow(target string) (*Response, error) { + _, resp, err := c.getResponse("PUT", fmt.Sprintf("/user/following/%s", target), nil, nil) + return resp, err } // Unfollow set current user unfollow the target -func (c *Client) Unfollow(target string) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/user/following/%s", target), nil, nil) - return err +func (c *Client) Unfollow(target string) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/following/%s", target), nil, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/user_gpgkey.go b/vendor/code.gitea.io/sdk/gitea/user_gpgkey.go index 026cb1ae8..d3d64b41e 100644 --- a/vendor/code.gitea.io/sdk/gitea/user_gpgkey.go +++ b/vendor/code.gitea.io/sdk/gitea/user_gpgkey.go @@ -39,23 +39,26 @@ type ListGPGKeysOptions struct { } // ListGPGKeys list all the GPG keys of the user -func (c *Client) ListGPGKeys(user string, opt ListGPGKeysOptions) ([]*GPGKey, error) { +func (c *Client) ListGPGKeys(user string, opt ListGPGKeysOptions) ([]*GPGKey, *Response, error) { opt.setDefaults() keys := make([]*GPGKey, 0, opt.PageSize) - return keys, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/gpg_keys?%s", user, opt.getURLQuery().Encode()), nil, nil, &keys) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/gpg_keys?%s", user, opt.getURLQuery().Encode()), nil, nil, &keys) + return keys, resp, err } // ListMyGPGKeys list all the GPG keys of current user -func (c *Client) ListMyGPGKeys(opt *ListGPGKeysOptions) ([]*GPGKey, error) { +func (c *Client) ListMyGPGKeys(opt *ListGPGKeysOptions) ([]*GPGKey, *Response, error) { opt.setDefaults() keys := make([]*GPGKey, 0, opt.PageSize) - return keys, c.getParsedResponse("GET", fmt.Sprintf("/user/gpg_keys?%s", opt.getURLQuery().Encode()), nil, nil, &keys) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/gpg_keys?%s", opt.getURLQuery().Encode()), nil, nil, &keys) + return keys, resp, err } // GetGPGKey get current user's GPG key by key id -func (c *Client) GetGPGKey(keyID int64) (*GPGKey, error) { +func (c *Client) GetGPGKey(keyID int64) (*GPGKey, *Response, error) { key := new(GPGKey) - return key, c.getParsedResponse("GET", fmt.Sprintf("/user/gpg_keys/%d", keyID), nil, nil, &key) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/gpg_keys/%d", keyID), nil, nil, &key) + return key, resp, err } // CreateGPGKeyOption options create user GPG key @@ -66,17 +69,18 @@ type CreateGPGKeyOption struct { } // CreateGPGKey create GPG key with options -func (c *Client) CreateGPGKey(opt CreateGPGKeyOption) (*GPGKey, error) { +func (c *Client) CreateGPGKey(opt CreateGPGKeyOption) (*GPGKey, *Response, error) { body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } key := new(GPGKey) - return key, c.getParsedResponse("POST", "/user/gpg_keys", jsonHeader, bytes.NewReader(body), key) + resp, err := c.getParsedResponse("POST", "/user/gpg_keys", jsonHeader, bytes.NewReader(body), key) + return key, resp, err } // DeleteGPGKey delete GPG key with key id -func (c *Client) DeleteGPGKey(keyID int64) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/user/gpg_keys/%d", keyID), nil, nil) - return err +func (c *Client) DeleteGPGKey(keyID int64) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/gpg_keys/%d", keyID), nil, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/user_key.go b/vendor/code.gitea.io/sdk/gitea/user_key.go index 6c7148758..d005f00be 100644 --- a/vendor/code.gitea.io/sdk/gitea/user_key.go +++ b/vendor/code.gitea.io/sdk/gitea/user_key.go @@ -30,23 +30,26 @@ type ListPublicKeysOptions struct { } // ListPublicKeys list all the public keys of the user -func (c *Client) ListPublicKeys(user string, opt ListPublicKeysOptions) ([]*PublicKey, error) { +func (c *Client) ListPublicKeys(user string, opt ListPublicKeysOptions) ([]*PublicKey, *Response, error) { opt.setDefaults() keys := make([]*PublicKey, 0, opt.PageSize) - return keys, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/keys?%s", user, opt.getURLQuery().Encode()), nil, nil, &keys) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/keys?%s", user, opt.getURLQuery().Encode()), nil, nil, &keys) + return keys, resp, err } // ListMyPublicKeys list all the public keys of current user -func (c *Client) ListMyPublicKeys(opt ListPublicKeysOptions) ([]*PublicKey, error) { +func (c *Client) ListMyPublicKeys(opt ListPublicKeysOptions) ([]*PublicKey, *Response, error) { opt.setDefaults() keys := make([]*PublicKey, 0, opt.PageSize) - return keys, c.getParsedResponse("GET", fmt.Sprintf("/user/keys?%s", opt.getURLQuery().Encode()), nil, nil, &keys) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/keys?%s", opt.getURLQuery().Encode()), nil, nil, &keys) + return keys, resp, err } // GetPublicKey get current user's public key by key id -func (c *Client) GetPublicKey(keyID int64) (*PublicKey, error) { +func (c *Client) GetPublicKey(keyID int64) (*PublicKey, *Response, error) { key := new(PublicKey) - return key, c.getParsedResponse("GET", fmt.Sprintf("/user/keys/%d", keyID), nil, nil, &key) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/keys/%d", keyID), nil, nil, &key) + return key, resp, err } // CreateKeyOption options when creating a key @@ -60,17 +63,18 @@ type CreateKeyOption struct { } // CreatePublicKey create public key with options -func (c *Client) CreatePublicKey(opt CreateKeyOption) (*PublicKey, error) { +func (c *Client) CreatePublicKey(opt CreateKeyOption) (*PublicKey, *Response, error) { body, err := json.Marshal(&opt) if err != nil { - return nil, err + return nil, nil, err } key := new(PublicKey) - return key, c.getParsedResponse("POST", "/user/keys", jsonHeader, bytes.NewReader(body), key) + resp, err := c.getParsedResponse("POST", "/user/keys", jsonHeader, bytes.NewReader(body), key) + return key, resp, err } // DeletePublicKey delete public key with key id -func (c *Client) DeletePublicKey(keyID int64) error { - _, err := c.getResponse("DELETE", fmt.Sprintf("/user/keys/%d", keyID), nil, nil) - return err +func (c *Client) DeletePublicKey(keyID int64) (*Response, error) { + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/keys/%d", keyID), nil, nil) + return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/user_search.go b/vendor/code.gitea.io/sdk/gitea/user_search.go index 5e098211f..7e4064d18 100644 --- a/vendor/code.gitea.io/sdk/gitea/user_search.go +++ b/vendor/code.gitea.io/sdk/gitea/user_search.go @@ -35,10 +35,10 @@ func (opt *SearchUsersOption) QueryEncode() string { } // SearchUsers finds users by query -func (c *Client) SearchUsers(opt SearchUsersOption) ([]*User, error) { +func (c *Client) SearchUsers(opt SearchUsersOption) ([]*User, *Response, error) { link, _ := url.Parse("/users/search") link.RawQuery = opt.QueryEncode() - resp := new(searchUsersResponse) - err := c.getParsedResponse("GET", link.String(), nil, nil, &resp) - return resp.Users, err + userResp := new(searchUsersResponse) + resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &userResp) + return userResp.Users, resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/version.go b/vendor/code.gitea.io/sdk/gitea/version.go index b0f1c7b09..c96ef66a6 100644 --- a/vendor/code.gitea.io/sdk/gitea/version.go +++ b/vendor/code.gitea.io/sdk/gitea/version.go @@ -11,24 +11,19 @@ import ( ) // ServerVersion returns the version of the server -func (c *Client) ServerVersion() (string, error) { +func (c *Client) ServerVersion() (string, *Response, error) { var v = struct { Version string `json:"version"` }{} - return v.Version, c.getParsedResponse("GET", "/version", nil, nil, &v) + resp, err := c.getParsedResponse("GET", "/version", nil, nil, &v) + return v.Version, resp, err } // CheckServerVersionConstraint validates that the login's server satisfies a // given version constraint such as ">= 1.11.0+dev" func (c *Client) CheckServerVersionConstraint(constraint string) error { - c.versionLock.RLock() - if c.serverVersion == nil { - c.versionLock.RUnlock() - if err := c.loadClientServerVersion(); err != nil { - return err - } - } else { - c.versionLock.RUnlock() + if err := c.loadServerVersion(); err != nil { + return err } check, err := version.NewConstraint(constraint) @@ -41,17 +36,37 @@ func (c *Client) CheckServerVersionConstraint(constraint string) error { return nil } -// loadClientServerVersion init the serverVersion variable -func (c *Client) loadClientServerVersion() error { - c.versionLock.Lock() - defer c.versionLock.Unlock() +// predefined versions only have to be parsed by library once +var ( + version1_11_0, _ = version.NewVersion("1.11.0") + version1_12_0, _ = version.NewVersion("1.12.0") + version1_13_0, _ = version.NewVersion("1.13.0") + version1_14_0, _ = version.NewVersion("1.14.0") +) - raw, err := c.ServerVersion() - if err != nil { +// checkServerVersionGreaterThanOrEqual is internally used to speed up things and ignore issues with prerelease +func (c *Client) checkServerVersionGreaterThanOrEqual(v *version.Version) error { + if err := c.loadServerVersion(); err != nil { return err } - if c.serverVersion, err = version.NewVersion(raw); err != nil { - return err + + if !c.serverVersion.GreaterThanOrEqual(v) { + return fmt.Errorf("gitea server at %s is older than %s", c.url, v.Original()) } return nil } + +// loadServerVersion init the serverVersion variable +func (c *Client) loadServerVersion() (err error) { + c.getVersionOnce.Do(func() { + raw, _, err2 := c.ServerVersion() + if err2 != nil { + err = err2 + return + } + if c.serverVersion, err = version.NewVersion(raw); err != nil { + return + } + }) + return +} diff --git a/vendor/github.com/hashicorp/go-version/.travis.yml b/vendor/github.com/hashicorp/go-version/.travis.yml deleted file mode 100644 index 01c5dc219..000000000 --- a/vendor/github.com/hashicorp/go-version/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: go - -go: - - 1.2 - - 1.3 - - 1.4 - - 1.9 - - "1.10" - - 1.11 - - 1.12 - -script: - - go test diff --git a/vendor/github.com/hashicorp/go-version/README.md b/vendor/github.com/hashicorp/go-version/README.md index 6f3a15ce7..851a337be 100644 --- a/vendor/github.com/hashicorp/go-version/README.md +++ b/vendor/github.com/hashicorp/go-version/README.md @@ -1,5 +1,6 @@ # Versioning Library for Go -[![Build Status](https://travis-ci.org/hashicorp/go-version.svg?branch=master)](https://travis-ci.org/hashicorp/go-version) +[![Build Status](https://circleci.com/gh/hashicorp/go-version/tree/master.svg?style=svg)](https://circleci.com/gh/hashicorp/go-version/tree/master) +[![GoDoc](https://godoc.org/github.com/hashicorp/go-version?status.svg)](https://godoc.org/github.com/hashicorp/go-version) go-version is a library for parsing versions and version constraints, and verifying versions against a set of constraints. go-version diff --git a/vendor/github.com/hashicorp/go-version/version.go b/vendor/github.com/hashicorp/go-version/version.go index 1032c5606..09703e8e6 100644 --- a/vendor/github.com/hashicorp/go-version/version.go +++ b/vendor/github.com/hashicorp/go-version/version.go @@ -280,6 +280,10 @@ func comparePrereleases(v string, other string) int { // Equal tests if two versions are equal. func (v *Version) Equal(o *Version) bool { + if v == nil || o == nil { + return v == o + } + return v.Compare(o) == 0 } @@ -288,7 +292,7 @@ func (v *Version) GreaterThan(o *Version) bool { return v.Compare(o) > 0 } -// GreaterThanOrEqualTo tests if this version is greater than or equal to another version. +// GreaterThanOrEqual tests if this version is greater than or equal to another version. func (v *Version) GreaterThanOrEqual(o *Version) bool { return v.Compare(o) >= 0 } @@ -298,7 +302,7 @@ func (v *Version) LessThan(o *Version) bool { return v.Compare(o) < 0 } -// LessThanOrEqualTo tests if this version is less than or equal to another version. +// LessThanOrEqual tests if this version is less than or equal to another version. func (v *Version) LessThanOrEqual(o *Version) bool { return v.Compare(o) <= 0 } diff --git a/vendor/github.com/jenkins-x/go-scm/pkg/hmac/hmac.go b/vendor/github.com/jenkins-x/go-scm/pkg/hmac/hmac.go index ba3fdf89d..9a90caed2 100644 --- a/vendor/github.com/jenkins-x/go-scm/pkg/hmac/hmac.go +++ b/vendor/github.com/jenkins-x/go-scm/pkg/hmac/hmac.go @@ -6,7 +6,7 @@ package hmac import ( "crypto/hmac" - "crypto/sha1" + "crypto/sha1" // #nosec "crypto/sha256" "encoding/hex" "hash" @@ -42,7 +42,7 @@ func ValidatePrefix(message, key []byte, signature string) bool { func validate(h func() hash.Hash, message, key, signature []byte) bool { mac := hmac.New(h, key) - mac.Write(message) + mac.Write(message) // #nosec sum := mac.Sum(nil) return hmac.Equal(signature, sum) } diff --git a/vendor/github.com/jenkins-x/go-scm/scm/app.go b/vendor/github.com/jenkins-x/go-scm/scm/app.go index b03783c94..0a7cddc06 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/app.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/app.go @@ -6,6 +6,7 @@ import ( ) type ( + // InstallationToken is the token used for interacting with the app InstallationToken struct { Token string ExpiresAt *time.Time diff --git a/vendor/github.com/jenkins-x/go-scm/scm/client.go b/vendor/github.com/jenkins-x/go-scm/scm/client.go index d1b1ea6ec..668a11399 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/client.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/client.go @@ -27,6 +27,11 @@ var ( // authorized or the user does not have access to the // resource. ErrNotAuthorized = errors.New("Not Authorized") + + // ErrForbidden indicates the user does not have access to + // the resource, this is similar to 401, but in this case, + // re-authenticating will make no difference. + ErrForbidden = errors.New("Forbidden") ) type ( @@ -73,6 +78,8 @@ type ( URL string Page int Size int + From string + To string } // GraphQLService the API to performing GraphQL queries @@ -92,6 +99,9 @@ type ( BaseURL *url.URL GraphQLURL *url.URL + // Username is the optional user name for the client + Username string + // Services used for communicating with the API. Driver Driver Apps AppService @@ -101,6 +111,8 @@ type ( GraphQL GraphQLService Organizations OrganizationService Issues IssueService + Milestones MilestoneService + Releases ReleaseService PullRequests PullRequestService Repositories RepositoryService Reviews ReviewService @@ -173,9 +185,9 @@ func (c *Client) Do(ctx context.Context, in *Request) (*Response, error) { // dumps the response for debugging purposes. if c.DumpResponse != nil { - c.DumpResponse(res, true) + _, err = c.DumpResponse(res, true) } - return newResponse(res), nil + return newResponse(res), err } // newResponse creates a new Response for the provided @@ -186,17 +198,17 @@ func newResponse(r *http.Response) *Response { Header: r.Header, Body: r.Body, } - res.populatePageValues() + res.PopulatePageValues() return res } -// populatePageValues parses the HTTP Link response headers +// PopulatePageValues parses the HTTP Link response headers // and populates the various pagination link values in the // Response. // // Copyright 2013 The go-github AUTHORS. All rights reserved. // https://github.com/google/go-github -func (r *Response) populatePageValues() { +func (r *Response) PopulatePageValues() { links := strings.Split(r.Header.Get("Link"), ",") for _, link := range links { segments := strings.Split(strings.TrimSpace(link), ";") diff --git a/vendor/github.com/jenkins-x/go-scm/scm/const.go b/vendor/github.com/jenkins-x/go-scm/scm/const.go index 53872926e..8cb7378c1 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/const.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/const.go @@ -71,10 +71,12 @@ func ToState(s string) State { } } +// MarshalJSON marshals State to JSON func (s State) MarshalJSON() ([]byte, error) { return []byte(fmt.Sprintf(`"%s"`, s.String())), nil } +// UnmarshalJSON unmarshals JSON to State func (s *State) UnmarshalJSON(b []byte) error { *s = ToState(strings.Trim(string(b), `"`)) return nil @@ -102,6 +104,7 @@ const ( ActionReviewRequested ActionReviewRequestRemoved ActionReadyForReview + ActionConvertedToDraft // reviews ActionEdited @@ -151,6 +154,8 @@ func (a Action) String() (s string) { return "review_request_removed" case ActionReadyForReview: return "ready_for_review" + case ActionConvertedToDraft: + return "converted_to_draft" case ActionCompleted: return "completed" default: @@ -194,6 +199,8 @@ func (a *Action) UnmarshalJSON(data []byte) error { *a = ActionCompleted case "ready_for_review": *a = ActionReadyForReview + case "converted_to_draft": + *a = ActionConvertedToDraft case "submitted": *a = ActionSubmitted case "dismissed": diff --git a/vendor/github.com/jenkins-x/go-scm/scm/deploy.go b/vendor/github.com/jenkins-x/go-scm/scm/deploy.go index 212b3a2f9..131e12a84 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/deploy.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/deploy.go @@ -14,6 +14,7 @@ type ( Link string Sha string Ref string + Task string FullName string Description string OriginalEnvironment string @@ -25,6 +26,7 @@ type ( Updated time.Time TransientEnvironment bool ProductionEnvironment bool + Payload interface{} } // DeploymentInput the input to create a new deployment diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/bitbucket.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/bitbucket.go index 9d4632227..8ed13c948 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/bitbucket.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/bitbucket.go @@ -9,13 +9,16 @@ import ( "bytes" "context" "encoding/json" + "errors" "io" + "net/http" "net/url" "strings" "github.com/jenkins-x/go-scm/scm" ) +// NewWebHookService creates a new instance of the webhook service without the rest of the client func NewWebHookService() scm.WebhookService { return &webhookService{nil} } @@ -36,6 +39,7 @@ func New(uri string) (*scm.Client, error) { client.Contents = &contentService{client} client.Git = &gitService{client} client.Issues = &issueService{client} + client.Milestones = &milestoneService{client} client.Organizations = &organizationService{client} client.PullRequests = &pullService{&issueService{client}} client.Repositories = &repositoryService{client} @@ -69,7 +73,7 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface // write it to the body of the request. if in != nil { buf := new(bytes.Buffer) - json.NewEncoder(buf).Encode(in) + json.NewEncoder(buf).Encode(in) // #nosec req.Header = map[string][]string{ "Content-Type": {"application/json"}, } @@ -88,9 +92,9 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface if res.Status == 401 { return res, scm.ErrNotAuthorized } else if res.Status > 300 { - err := new(Error) - json.NewDecoder(res.Body).Decode(err) - return res, err + return res, errors.New( + http.StatusText(res.Status), + ) } if out == nil { @@ -100,8 +104,8 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface // if raw output is expected, copy to the provided // buffer and exit. if w, ok := out.(io.Writer); ok { - io.Copy(w, res.Body) - return res, nil + _, err := io.Copy(w, res.Body) + return res, err } // if a json response is expected, parse and return diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/git.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/git.go index 6529bb1fc..d92501564 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/git.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/git.go @@ -18,8 +18,9 @@ type gitService struct { } func (s *gitService) FindRef(ctx context.Context, repo, ref string) (string, *scm.Response, error) { + ref = strings.TrimPrefix(ref, "heads/") commit, res, err := s.FindCommit(ctx, repo, ref) - if err != nil && res.Status != 404 { + if err != nil && res == nil || (res.Status != 404 && res.Status >= 300) { return "", res, err } if commit != nil { @@ -84,7 +85,10 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, opts scm.Lis path := fmt.Sprintf("2.0/repositories/%s/refs/branches?%s", repo, encodeListOptions(opts)) out := new(branches) res, err := s.client.do(ctx, "GET", path, nil, out) - copyPagination(out.pagination, res) + if err != nil { + return nil, res, err + } + err = copyPagination(out.pagination, res) return convertBranchList(out), res, err } @@ -92,7 +96,10 @@ func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.Comm path := fmt.Sprintf("2.0/repositories/%s/commits/%s?%s", repo, opts.Ref, encodeCommitListOptions(opts)) out := new(commits) res, err := s.client.do(ctx, "GET", path, nil, out) - copyPagination(out.pagination, res) + if err != nil { + return nil, res, err + } + err = copyPagination(out.pagination, res) return convertCommitList(out), res, err } @@ -100,7 +107,10 @@ func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOpt path := fmt.Sprintf("2.0/repositories/%s/refs/tags?%s", repo, encodeListOptions(opts)) out := new(branches) res, err := s.client.do(ctx, "GET", path, nil, &out) - copyPagination(out.pagination, res) + if err != nil { + return nil, res, err + } + err = copyPagination(out.pagination, res) return convertTagList(out), res, err } @@ -108,7 +118,21 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, opts scm path := fmt.Sprintf("2.0/repositories/%s/diffstat/%s?%s", repo, ref, encodeListOptions(opts)) out := new(diffstats) res, err := s.client.do(ctx, "GET", path, nil, &out) - copyPagination(out.pagination, res) + if err != nil { + return nil, res, err + } + err = copyPagination(out.pagination, res) + return convertDiffstats(out), res, err +} + +func (s *gitService) CompareCommits(ctx context.Context, repo, ref1, ref2 string, opts scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + path := fmt.Sprintf("2.0/repositories/%s/diffstat/%s..%s?%s", repo, ref1, ref2, encodeListOptions(opts)) + out := new(diffstats) + res, err := s.client.do(ctx, "GET", path, nil, &out) + if err != nil { + return nil, res, err + } + err = copyPagination(out.pagination, res) return convertDiffstats(out), res, err } diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/issue.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/issue.go index 8f463d681..1b7f0b947 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/issue.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/issue.go @@ -7,6 +7,8 @@ package bitbucket import ( "context" + "github.com/jenkins-x/go-scm/scm/labels" + "github.com/jenkins-x/go-scm/scm" ) @@ -30,16 +32,26 @@ func (s *issueService) ListEvents(context.Context, string, int, scm.ListOptions) return nil, nil, scm.ErrNotSupported } -func (s *issueService) ListLabels(context.Context, string, int, scm.ListOptions) ([]*scm.Label, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported +func (s *issueService) ListLabels(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Label, *scm.Response, error) { + // Get all comments, parse out labels (removing and added based off time) + cs, res, err := s.ListComments(ctx, repo, number, opts) + if err == nil { + l, err := labels.ConvertLabelComments(cs) + return l, res, err + } + return nil, res, err } func (s *issueService) AddLabel(ctx context.Context, repo string, number int, label string) (*scm.Response, error) { - return nil, scm.ErrNotSupported + input := labels.CreateLabelAddComment(label) + _, res, err := s.CreateComment(ctx, repo, number, input) + return res, err } func (s *issueService) DeleteLabel(ctx context.Context, repo string, number int, label string) (*scm.Response, error) { - return nil, scm.ErrNotSupported + input := labels.CreateLabelRemoveComment(label) + _, res, err := s.CreateComment(ctx, repo, number, input) + return res, err } func (s *issueService) Find(ctx context.Context, repo string, number int) (*scm.Issue, *scm.Response, error) { @@ -89,3 +101,11 @@ func (s *issueService) Lock(ctx context.Context, repo string, number int) (*scm. func (s *issueService) Unlock(ctx context.Context, repo string, number int) (*scm.Response, error) { return nil, scm.ErrNotSupported } + +func (s *issueService) SetMilestone(ctx context.Context, repo string, issueID int, number int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *issueService) ClearMilestone(ctx context.Context, repo string, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/milestone.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/milestone.go new file mode 100644 index 000000000..84cd2b49b --- /dev/null +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/milestone.go @@ -0,0 +1,31 @@ +package bitbucket + +import ( + "context" + + "github.com/jenkins-x/go-scm/scm" +) + +type milestoneService struct { + client *wrapper +} + +func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *milestoneService) List(ctx context.Context, repo string, opts scm.MilestoneListOptions) ([]*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/org.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/org.go index a4b07eb93..14389bca8 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/org.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/org.go @@ -15,6 +15,14 @@ type organizationService struct { client *wrapper } +func (s *organizationService) Create(context.Context, *scm.OrganizationInput) (*scm.Organization, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *organizationService) Delete(context.Context, string) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + func (s *organizationService) IsMember(ctx context.Context, org string, user string) (bool, *scm.Response, error) { return false, nil, scm.ErrNotSupported } @@ -46,10 +54,25 @@ func (s *organizationService) List(ctx context.Context, opts scm.ListOptions) ([ path := fmt.Sprintf("2.0/teams?%s", encodeListRoleOptions(opts)) out := new(organizationList) res, err := s.client.do(ctx, "GET", path, nil, out) - copyPagination(out.pagination, res) + if err != nil { + return nil, res, err + } + err = copyPagination(out.pagination, res) return convertOrganizationList(out), res, err } +func (s *organizationService) ListPendingInvitations(ctx context.Context, org string, opts scm.ListOptions) ([]*scm.OrganizationPendingInvite, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *organizationService) AcceptOrganizationInvitation(ctx context.Context, org string) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *organizationService) ListMemberships(ctx context.Context, opts scm.ListOptions) ([]*scm.Membership, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + func convertOrganizationList(from *organizationList) []*scm.Organization { to := []*scm.Organization{} for _, v := range from.Values { diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/pr.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/pr.go index 70b715f43..f0eb3e2f6 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/pr.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/pr.go @@ -11,6 +11,8 @@ import ( "strings" "time" + "github.com/jenkins-x/go-scm/scm/labels" + "github.com/jenkins-x/go-scm/scm" ) @@ -37,7 +39,10 @@ func (s *pullService) List(ctx context.Context, repo string, opts scm.PullReques return nil, res, err } res, err := s.client.do(ctx, "GET", path, nil, out) - copyPagination(out.pagination, res) + if err != nil { + return nil, res, err + } + err = copyPagination(out.pagination, res) return convertPullRequests(out), res, err } @@ -45,20 +50,37 @@ func (s *pullService) ListChanges(ctx context.Context, repo string, number int, path := fmt.Sprintf("2.0/repositories/%s/pullrequests/%d/diffstat?%s", repo, number, encodeListOptions(opts)) out := new(diffstats) res, err := s.client.do(ctx, "GET", path, nil, out) - copyPagination(out.pagination, res) + if err != nil { + return nil, res, err + } + err = copyPagination(out.pagination, res) return convertDiffstats(out), res, err } -func (s *pullService) ListLabels(context.Context, string, int, scm.ListOptions) ([]*scm.Label, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported +func (s *pullService) ListLabels(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Label, *scm.Response, error) { + // Get all comments, parse out labels (removing and added based off time) + cs, res, err := s.ListComments(ctx, repo, number, opts) + if err == nil { + l, err := labels.ConvertLabelComments(cs) + return l, res, err + } + return nil, res, err } -func (s *pullService) ListEvents(context.Context, string, int, scm.ListOptions) ([]*scm.ListedIssueEvent, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported +func (s *pullService) AddLabel(ctx context.Context, repo string, number int, label string) (*scm.Response, error) { + input := labels.CreateLabelAddComment(label) + _, res, err := s.CreateComment(ctx, repo, number, input) + return res, err } func (s *pullService) DeleteLabel(ctx context.Context, repo string, number int, label string) (*scm.Response, error) { - return nil, scm.ErrNotSupported + input := labels.CreateLabelRemoveComment(label) + _, res, err := s.CreateComment(ctx, repo, number, input) + return res, err +} + +func (s *pullService) ListEvents(context.Context, string, int, scm.ListOptions) ([]*scm.ListedIssueEvent, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported } func (s *pullService) Merge(ctx context.Context, repo string, number int, options *scm.PullRequestMergeOptions) (*scm.Response, error) { @@ -87,8 +109,33 @@ func (s *pullService) UnassignIssue(ctx context.Context, repo string, number int return nil, scm.ErrNotSupported } +type prPatchName struct { + Name string `json:"name"` +} + +type prPatchBranch struct { + Branch prPatchName `json:"branch,omitempty"` +} + +type prInput struct { + Title string `json:"title,omitempty"` + Source prPatchBranch `json:"source,omitempty"` + Project string +} + func (s *pullService) Create(ctx context.Context, repo string, input *scm.PullRequestInput) (*scm.PullRequest, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + path := fmt.Sprintf("2.0/repositories/%s/pullrequests", repo) + in := &prInput{ + Title: input.Title, + Source: prPatchBranch{ + Branch: prPatchName{ + Name: input.Head, + }, + }, + } + out := new(pullRequest) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertPullRequest(out), res, err } func (s *pullService) RequestReview(ctx context.Context, repo string, number int, logins []string) (*scm.Response, error) { diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/repo.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/repo.go index 04612b6ed..577ac7123 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/repo.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/repo.go @@ -7,12 +7,24 @@ package bitbucket import ( "context" "fmt" + "io/ioutil" "net/url" + "strings" "time" + "github.com/pkg/errors" + "github.com/jenkins-x/go-scm/scm" ) +type repositoryInput struct { + SCM string `json:"scm,omitempty"` + Project struct { + Key string `json:"key,omitempty"` + } `json:"project,omitempty"` + Private bool `json:"is_private,omitempty"` +} + type repository struct { UUID string `json:"uuid"` SCM string `json:"scm"` @@ -59,8 +71,50 @@ type repositoryService struct { client *wrapper } -func (s *repositoryService) Create(context.Context, *scm.RepositoryInput) (*scm.Repository, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported +func (s *repositoryService) Create(ctx context.Context, input *scm.RepositoryInput) (*scm.Repository, *scm.Response, error) { + workspace := input.Namespace + if workspace == "" { + workspace = s.client.Username + } + projectKey := "" + if workspace == "" { + user, res, err := s.client.Users.Find(ctx) + if err != nil { + return nil, res, errors.Wrapf(err, "failed to find current user") + } + workspace = user.Login + if workspace == "" { + return nil, nil, errors.Errorf("failed to find current user login") + } + s.client.Username = workspace + } + + // lets allow the projectKey to be specified as workspace:projectKey + words := strings.SplitN(workspace, ":", 2) + if len(words) > 1 { + workspace = words[0] + projectKey = words[1] + } + path := fmt.Sprintf("2.0/repositories/%s/%s", workspace, input.Name) + out := new(repository) + in := new(repositoryInput) + in.SCM = "git" + in.Project.Key = projectKey + in.Private = input.Private + res, err := s.client.do(ctx, "POST", path, in, out) + return convertRepository(out), res, wrapError(res, err) + +} + +func wrapError(res *scm.Response, err error) error { + if res == nil { + return err + } + data, err2 := ioutil.ReadAll(res.Body) + if err2 != nil { + return errors.Wrapf(err, "http status %d", res.Status) + } + return errors.Wrapf(err, "http status %d mesage %s", res.Status, string(data)) } func (s *repositoryService) Fork(context.Context, *scm.RepositoryInput, string) (*scm.Repository, *scm.Response, error) { @@ -76,19 +130,25 @@ func (s *repositoryService) FindUserPermission(ctx context.Context, repo string, } func (s *repositoryService) AddCollaborator(ctx context.Context, repo, user, permission string) (bool, bool, *scm.Response, error) { - return false, false, nil, scm.ErrNotSupported + // TODO lets fake out this method for now + return true, false, nil, nil } func (s *repositoryService) IsCollaborator(ctx context.Context, repo, user string) (bool, *scm.Response, error) { - return false, nil, scm.ErrNotSupported + // TODO lets fake out this method for now + return true, nil, nil } func (s *repositoryService) ListCollaborators(ctx context.Context, repo string, ops scm.ListOptions) ([]scm.User, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + return nil, nil, nil } func (s *repositoryService) ListLabels(context.Context, string, scm.ListOptions) ([]*scm.Label, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + return nil, nil, nil +} + +func (s *repositoryService) Delete(context.Context, string) (*scm.Response, error) { + return nil, scm.ErrNotSupported } // Find returns the repository by name. @@ -96,7 +156,7 @@ func (s *repositoryService) Find(ctx context.Context, repo string) (*scm.Reposit path := fmt.Sprintf("2.0/repositories/%s", repo) out := new(repository) res, err := s.client.do(ctx, "GET", path, nil, out) - return convertRepository(out), res, err + return convertRepository(out), res, wrapError(res, err) } // FindHook returns a repository hook. @@ -104,7 +164,7 @@ func (s *repositoryService) FindHook(ctx context.Context, repo string, id string path := fmt.Sprintf("2.0/repositories/%s/hooks/%s", repo, id) out := new(hook) res, err := s.client.do(ctx, "GET", path, nil, out) - return convertHook(out), res, err + return convertHook(out), res, wrapError(res, err) } // FindPerms returns the repository permissions. @@ -112,7 +172,7 @@ func (s *repositoryService) FindPerms(ctx context.Context, repo string) (*scm.Pe path := fmt.Sprintf("2.0/user/permissions/repositories?q=repository.full_name=%q", repo) out := new(perms) res, err := s.client.do(ctx, "GET", path, nil, out) - return convertPerms(out), res, err + return convertPerms(out), res, wrapError(res, err) } // List returns the user repository list. @@ -123,8 +183,11 @@ func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* } out := new(repositories) res, err := s.client.do(ctx, "GET", path, nil, &out) - copyPagination(out.pagination, res) - return convertRepositoryList(out), res, err + if err != nil { + return nil, res, wrapError(res, err) + } + err = copyPagination(out.pagination, res) + return convertRepositoryList(out), res, wrapError(res, err) } func (s *repositoryService) ListOrganisation(context.Context, string, scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { @@ -140,8 +203,11 @@ func (s *repositoryService) ListHooks(ctx context.Context, repo string, opts scm path := fmt.Sprintf("2.0/repositories/%s/hooks?%s", repo, encodeListOptions(opts)) out := new(hooks) res, err := s.client.do(ctx, "GET", path, nil, out) - copyPagination(out.pagination, res) - return convertHookList(out), res, err + if err != nil { + return nil, res, wrapError(res, err) + } + err = copyPagination(out.pagination, res) + return convertHookList(out), res, wrapError(res, err) } // ListStatus returns a list of commit statuses. @@ -149,32 +215,42 @@ func (s *repositoryService) ListStatus(ctx context.Context, repo, ref string, op path := fmt.Sprintf("2.0/repositories/%s/commit/%s/statuses?%s", repo, ref, encodeListOptions(opts)) out := new(statuses) res, err := s.client.do(ctx, "GET", path, nil, out) - copyPagination(out.pagination, res) - return convertStatusList(out), res, err + if err != nil { + return nil, res, wrapError(res, err) + } + err = copyPagination(out.pagination, res) + return convertStatusList(out), res, wrapError(res, err) } // CreateHook creates a new repository webhook. func (s *repositoryService) CreateHook(ctx context.Context, repo string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) { - target, err := url.Parse(input.Target) - if err != nil { - return nil, nil, err + targetText := input.Target + if input.Secret != "" { + target, err := url.Parse(input.Target) + if err != nil { + return nil, nil, err + } + params := target.Query() + params.Set("secret", input.Secret) + target.RawQuery = params.Encode() + targetText = target.String() } - params := target.Query() - params.Set("secret", input.Secret) - target.RawQuery = params.Encode() path := fmt.Sprintf("2.0/repositories/%s/hooks", repo) in := new(hookInput) - in.URL = target.String() + in.URL = targetText in.Active = true in.Description = input.Name + if in.Description == "" { + in.Description = "my webhook" + } in.Events = append( input.NativeEvents, convertHookEvents(input.Events)..., ) out := new(hook) res, err := s.client.do(ctx, "POST", path, in, out) - return convertHook(out), res, err + return convertHook(out), res, wrapError(res, err) } // CreateStatus creates a new commit status. @@ -189,7 +265,7 @@ func (s *repositoryService) CreateStatus(ctx context.Context, repo, ref string, } out := new(status) res, err := s.client.do(ctx, "POST", path, in, out) - return convertStatus(out), res, err + return convertStatus(out), res, wrapError(res, err) } // DeleteHook deletes a repository webhook. @@ -271,12 +347,14 @@ func convertHookEvents(from scm.HookEvents) []string { events = append(events, "repo:push") } if from.PullRequest { + events = append(events, "pullrequest:created") events = append(events, "pullrequest:updated") - events = append(events, "pullrequest:unapproved") + events = append(events, "pullrequest:changes_request_created") + events = append(events, "pullrequest:changes_request_removed") events = append(events, "pullrequest:approved") - events = append(events, "pullrequest:rejected") + events = append(events, "pullrequest:unapproved") events = append(events, "pullrequest:fulfilled") - events = append(events, "pullrequest:created") + events = append(events, "pullrequest:rejected") } if from.PullRequestComment { events = append(events, "pullrequest:comment_created") @@ -284,7 +362,6 @@ func convertHookEvents(from scm.HookEvents) []string { events = append(events, "pullrequest:comment_deleted") } if from.Issue { - events = append(events, "issues") events = append(events, "issue:created") events = append(events, "issue:updated") } diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/user.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/user.go index 079392ddf..77119ce30 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/user.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/user.go @@ -15,6 +15,14 @@ type userService struct { client *wrapper } +func (s *userService) CreateToken(context.Context, string, string) (*scm.UserToken, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *userService) DeleteToken(context.Context, int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + func (s *userService) Find(ctx context.Context) (*scm.User, *scm.Response, error) { out := new(user) res, err := s.client.do(ctx, "GET", "2.0/user", nil, out) diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/webhook.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/webhook.go index 0a3fde66f..ab71c13fe 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/webhook.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/bitbucket/webhook.go @@ -5,14 +5,17 @@ package bitbucket import ( + "context" "encoding/json" - "errors" "fmt" "io" "io/ioutil" "net/http" + "strings" "time" + "github.com/pkg/errors" + "github.com/jenkins-x/go-scm/scm" ) @@ -98,7 +101,7 @@ func (s *webhookService) parsePushHook(data []byte) (scm.Webhook, error) { case change.Old.Type == "tag" && change.Closed: return convertTagDeleteHook(dst), nil default: - return convertPushHook(dst), err + return s.convertPushHook(dst) } } @@ -111,7 +114,7 @@ func (s *webhookService) parsePullRequestHook(data []byte) (*scm.PullRequestHook switch { default: - return convertPullRequestHook(dst), err + return s.convertPullRequestHook(dst) } } @@ -489,13 +492,27 @@ type ( // push hooks // -func convertPushHook(src *pushHook) *scm.PushHook { +func (s *webhookService) convertPushHook(src *pushHook) (*scm.PushHook, error) { change := src.Push.Changes[0] namespace, name := scm.Split(src.Repository.FullName) + repo := scm.Repository{ + ID: src.Repository.UUID, + Namespace: namespace, + Name: name, + FullName: src.Repository.FullName, + Private: src.Repository.IsPrivate, + Clone: fmt.Sprintf("https://bitbucket.org/%s.git", src.Repository.FullName), + CloneSSH: fmt.Sprintf("git@bitbucket.org:%s.git", src.Repository.FullName), + Link: src.Repository.Links.HTML.Href, + } + if repo.FullName == "" { + repo.FullName = scm.Join(repo.Namespace, repo.Name) + } + sha := change.New.Target.Hash dst := &scm.PushHook{ Ref: scm.ExpandRef(change.New.Name, "refs/heads/"), Commit: scm.Commit{ - Sha: change.New.Target.Hash, + Sha: sha, Message: change.New.Target.Message, Link: change.New.Target.Links.HTML.Href, Author: scm.Signature{ @@ -513,16 +530,7 @@ func convertPushHook(src *pushHook) *scm.PushHook { Date: change.New.Target.Date, }, }, - Repo: scm.Repository{ - ID: src.Repository.UUID, - Namespace: namespace, - Name: name, - FullName: src.Repository.FullName, - Private: src.Repository.IsPrivate, - Clone: fmt.Sprintf("https://bitbucket.org/%s.git", src.Repository.FullName), - CloneSSH: fmt.Sprintf("git@bitbucket.org:%s.git", src.Repository.FullName), - Link: src.Repository.Links.HTML.Href, - }, + Repo: repo, Sender: scm.User{ Login: src.Actor.Username, Name: src.Actor.DisplayName, @@ -532,7 +540,20 @@ func convertPushHook(src *pushHook) *scm.PushHook { if change.New.Type == "tag" { dst.Ref = scm.ExpandRef(change.New.Name, "refs/tags/") } - return dst + dst.After = sha + if len(sha) <= 12 && sha != "" { + // lets convert to a full hash + repo := repo.FullName + fullHash, _, err := s.client.Git.FindRef(context.TODO(), repo, sha) + if err != nil { + return nil, errors.Wrapf(err, "failed to resolve full hash %s", sha) + } + fullHash = strings.TrimSpace(fullHash) + if fullHash != "" { + dst.After = fullHash + } + } + return dst, nil } func convertBranchCreateHook(src *pushHook) *scm.BranchHook { @@ -651,15 +672,26 @@ func convertTagDeleteHook(src *pushHook) *scm.TagHook { // pull request hooks // -func convertPullRequestHook(src *webhook) *scm.PullRequestHook { +func (s *webhookService) convertPullRequestHook(src *webhook) (*scm.PullRequestHook, error) { namespace, name := scm.Split(src.Repository.FullName) - return &scm.PullRequestHook{ + repo := scm.Repository{ + ID: src.Repository.UUID, + Namespace: namespace, + Name: name, + FullName: src.Repository.FullName, + Private: src.Repository.IsPrivate, + Clone: fmt.Sprintf("https://bitbucket.org/%s.git", src.Repository.FullName), + CloneSSH: fmt.Sprintf("git@bitbucket.org:%s.git", src.Repository.FullName), + Link: src.Repository.Links.HTML.Href, + } + sha := src.PullRequest.Source.Commit.Hash + dst := &scm.PullRequestHook{ Action: scm.ActionOpen, PullRequest: scm.PullRequest{ Number: src.PullRequest.ID, Title: src.PullRequest.Title, Body: src.PullRequest.Description, - Sha: src.PullRequest.Source.Commit.Hash, + Sha: sha, Ref: fmt.Sprintf("refs/pull-requests/%d/from", src.PullRequest.ID), Source: src.PullRequest.Source.Branch.Name, Target: src.PullRequest.Destination.Branch.Name, @@ -675,20 +707,39 @@ func convertPullRequestHook(src *webhook) *scm.PullRequestHook { Created: src.PullRequest.CreatedOn, Updated: src.PullRequest.UpdatedOn, }, - Repo: scm.Repository{ - ID: src.Repository.UUID, - Namespace: namespace, - Name: name, - FullName: src.Repository.FullName, - Private: src.Repository.IsPrivate, - Clone: fmt.Sprintf("https://bitbucket.org/%s.git", src.Repository.FullName), - CloneSSH: fmt.Sprintf("git@bitbucket.org:%s.git", src.Repository.FullName), - Link: src.Repository.Links.HTML.Href, - }, + Repo: repo, Sender: scm.User{ Login: src.Actor.Username, Name: src.Actor.DisplayName, Avatar: src.Actor.Links.Avatar.Href, }, } + dst.PullRequest.Base.Repo = repo + dst.PullRequest.Base.Ref = src.PullRequest.Destination.Branch.Name + dst.PullRequest.Head.Ref = src.PullRequest.Source.Branch.Name + + if len(sha) <= 12 && sha != "" && s.client != nil { + // lets convert to a full hash + repo := repo.FullName + fullHash, _, err := s.client.Git.FindRef(context.TODO(), repo, sha) + if err != nil { + return nil, errors.Wrapf(err, "failed to resolve full hash %s", sha) + } + fullHash = strings.TrimSpace(fullHash) + if fullHash != "" { + dst.PullRequest.Sha = fullHash + } + } + if dst.PullRequest.Head.Sha == "" && dst.PullRequest.Head.Ref != "" && s.client != nil { + repo := repo.FullName + fullHash, _, err := s.client.Git.FindRef(context.TODO(), repo, dst.PullRequest.Head.Ref) + if err != nil { + return nil, errors.Wrapf(err, "failed to resolve sha for ref %s", dst.PullRequest.Head.Ref) + } + fullHash = strings.TrimSpace(fullHash) + if fullHash != "" { + dst.PullRequest.Head.Sha = fullHash + } + } + return dst, nil } diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/content.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/content.go index 1dac6e666..83c9176f8 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/content.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/content.go @@ -32,7 +32,7 @@ func (c contentService) Find(_ context.Context, repo, path, ref string) (*scm.Co Status: 404, }, errors.Wrapf(err, "file %s does not exist", f) } - data, err := ioutil.ReadFile(f) + data, err := ioutil.ReadFile(f) // #nosec if err != nil { return nil, nil, errors.Wrapf(err, "failed to read file %s", f) } @@ -112,5 +112,30 @@ func (c contentService) path(repo string, path string, ref string) (string, erro if c.data.ContentDir == "" { return "", errors.Errorf("no data.ContentDir configured") } - return filepath.Join(c.data.ContentDir, repo, path), nil + if ref == "" { + ref = "master" + } + repoDir := filepath.Join(c.data.ContentDir, repo) + + // lets see if there's a 'refs' folder for testing out different files in different ref/shas + refDir := filepath.Join(repoDir, "refs", ref) + exists, err := DirExists(refDir) + if err != nil { + return repoDir, errors.Wrapf(err, "failed to check if refs dir %s exists", refDir) + } + if exists { + repoDir = refDir + } + return filepath.Join(repoDir, path), nil +} + +// DirExists checks if path exists and is a directory +func DirExists(path string) (bool, error) { + info, err := os.Stat(path) + if err == nil { + return info.IsDir(), nil + } else if os.IsNotExist(err) { + return false, nil + } + return false, err } diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/data.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/data.go index 8a722ad85..dde99d409 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/data.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/data.go @@ -2,6 +2,7 @@ package fake import "github.com/jenkins-x/go-scm/scm" +// Data is used to store/represent test data for the fake client type Data struct { Issues map[int][]*scm.Issue OrgMembers map[string][]string @@ -30,6 +31,9 @@ type Data struct { CurrentUser scm.User Users []*scm.User Hooks map[string][]*scm.Hook + Releases map[string]map[int]*scm.Release + Deployments map[string][]*scm.Deployment + DeploymentStatus map[string][]*scm.DeploymentStatus //All Labels That Exist In The Repo RepoLabelsExisting []string @@ -67,10 +71,14 @@ type Data struct { UserPermissions map[string]map[string]string + // Invitations the current pending invitations + Invitations []*scm.Invitation + // ContentDir the directory used to implement the Content service to access files and directories ContentDir string } +// DeletedRef represents a ref that has been deleted type DeletedRef struct { Org, Repo, Ref string } @@ -107,5 +115,7 @@ func NewData() *Data { AssigneesAdded: []string{}, UserPermissions: map[string]map[string]string{}, Hooks: map[string][]*scm.Hook{}, + Deployments: map[string][]*scm.Deployment{}, + DeploymentStatus: map[string][]*scm.DeploymentStatus{}, } } diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/deploy.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/deploy.go new file mode 100644 index 000000000..d09bd5601 --- /dev/null +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/deploy.go @@ -0,0 +1,110 @@ +package fake + +import ( + "context" + "strconv" + "time" + + "github.com/jenkins-x/go-scm/scm" +) + +type deploymentService struct { + client *wrapper + data *Data +} + +func (s *deploymentService) Find(ctx context.Context, repoFullName string, deploymentID string) (*scm.Deployment, *scm.Response, error) { + for _, d := range s.data.Deployments[repoFullName] { + if d.ID == deploymentID { + return d, nil, nil + } + } + return nil, nil, scm.ErrNotFound +} + +func (s *deploymentService) List(ctx context.Context, repoFullName string, opts scm.ListOptions) ([]*scm.Deployment, *scm.Response, error) { + return s.data.Deployments[repoFullName], nil, nil +} + +func (s *deploymentService) Create(ctx context.Context, repoFullName string, input *scm.DeploymentInput) (*scm.Deployment, *scm.Response, error) { + deployments := s.data.Deployments[repoFullName] + owner, name := scm.Split(repoFullName) + + d := &scm.Deployment{ + ID: "deployment-" + strconv.Itoa(len(deployments)+1), + Namespace: owner, + Name: name, + Link: "", + Sha: "", + Ref: input.Ref, + Task: input.Task, + FullName: "", + Description: input.Description, + OriginalEnvironment: input.Environment, + Environment: input.Environment, + RepositoryLink: "", + StatusLink: "", + Author: nil, + Created: time.Time{}, + Updated: time.Time{}, + TransientEnvironment: input.TransientEnvironment, + ProductionEnvironment: input.ProductionEnvironment, + Payload: input.Payload, + } + + s.data.Deployments[repoFullName] = append(deployments, d) + return d, nil, nil +} + +func (s *deploymentService) Delete(ctx context.Context, repoFullName string, deploymentID string) (*scm.Response, error) { + deployments := s.data.Deployments[repoFullName] + for i, d := range deployments { + if d.ID == deploymentID { + result := deployments[0:i] + if i+1 < len(deployments) { + result = append(result, deployments[i+1:]...) + } + s.data.Deployments[repoFullName] = result + return nil, nil + } + } + return nil, scm.ErrNotFound +} + +func (s *deploymentService) FindStatus(ctx context.Context, repoFullName string, deploymentID string, statusID string) (*scm.DeploymentStatus, *scm.Response, error) { + key := scm.Join(repoFullName, deploymentID) + for _, d := range s.data.DeploymentStatus[key] { + if d.ID == statusID { + return d, nil, nil + } + } + return nil, nil, scm.ErrNotFound +} + +func (s *deploymentService) ListStatus(ctx context.Context, repoFullName string, deploymentID string, opts scm.ListOptions) ([]*scm.DeploymentStatus, *scm.Response, error) { + key := scm.Join(repoFullName, deploymentID) + return s.data.DeploymentStatus[key], nil, nil +} + +func (s *deploymentService) CreateStatus(ctx context.Context, repoFullName string, deploymentID string, input *scm.DeploymentStatusInput) (*scm.DeploymentStatus, *scm.Response, error) { + key := scm.Join(repoFullName, deploymentID) + statuses := s.data.DeploymentStatus[key] + + status := &scm.DeploymentStatus{ + ID: "status-" + strconv.Itoa(len(statuses)+1), + State: input.State, + Author: nil, + Description: input.Description, + Environment: input.Environment, + DeploymentLink: "", + EnvironmentLink: input.EnvironmentLink, + LogLink: input.LogLink, + RepositoryLink: "", + TargetLink: input.LogLink, + Created: time.Time{}, + Updated: time.Time{}, + } + + s.data.DeploymentStatus[key] = append(statuses, status) + return status, nil, nil +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/fake.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/fake.go index 8f3c39e10..777bac3bf 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/fake.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/fake.go @@ -23,14 +23,16 @@ func NewDefault() (*scm.Client, *Data) { // initialize services client.Driver = scm.DriverFake + client.Contents = &contentService{client: client, data: data} + client.Deployments = &deploymentService{client: client, data: data} client.Git = &gitService{client: client, data: data} client.Issues = &issueService{client: client, data: data} client.Organizations = &organizationService{client: client, data: data} client.PullRequests = &pullService{client: client, data: data} client.Repositories = &repositoryService{client: client, data: data} + client.Releases = &releaseService{client: client, data: data} client.Reviews = &reviewService{client: client, data: data} client.Users = &userService{client: client, data: data} - client.Contents = &contentService{client: client, data: data} // TODO /* diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/git.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/git.go index 083775939..18a46cc40 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/git.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/git.go @@ -59,6 +59,10 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, opts scm panic("implement me") } +func (s *gitService) CompareCommits(ctx context.Context, repo, ref1, ref2 string, opts scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + panic("implement me") +} + func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { panic("implement me") } diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/issue.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/issue.go index 6f8aa62a4..f3a0ec297 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/issue.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/issue.go @@ -180,3 +180,11 @@ func (s *issueService) Lock(context.Context, string, int) (*scm.Response, error) func (s *issueService) Unlock(context.Context, string, int) (*scm.Response, error) { panic("implement me") } + +func (s *issueService) SetMilestone(ctx context.Context, repo string, issueID int, number int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *issueService) ClearMilestone(ctx context.Context, repo string, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/org.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/org.go index 3744a5bb0..46723ee09 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/org.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/org.go @@ -27,6 +27,14 @@ type organizationService struct { data *Data } +func (s *organizationService) Create(context.Context, *scm.OrganizationInput) (*scm.Organization, *scm.Response, error) { + panic("implement me") +} + +func (s *organizationService) Delete(context.Context, string) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + func (s *organizationService) IsMember(ctx context.Context, org string, user string) (bool, *scm.Response, error) { panic("implement me") } @@ -54,9 +62,9 @@ func (s *organizationService) List(context.Context, scm.ListOptions) ([]*scm.Org Name: fmt.Sprintf("organisation%d", i), Avatar: fmt.Sprintf("https://github.com/organisation%d.png", i), Permissions: scm.Permissions{ - true, - true, - true, + MembersCreatePrivate: true, + MembersCreatePublic: true, + MembersCreateInternal: true, }, } orgs = append(orgs, &org) @@ -96,3 +104,41 @@ func (s *organizationService) ListTeamMembers(ctx context.Context, teamID int, r func (s *organizationService) ListOrgMembers(ctx context.Context, org string, ops scm.ListOptions) ([]*scm.TeamMember, *scm.Response, error) { return nil, nil, scm.ErrNotSupported } +func (s *organizationService) ListPendingInvitations(_ context.Context, org string, opts scm.ListOptions) ([]*scm.OrganizationPendingInvite, *scm.Response, error) { + for _, o := range s.data.Organizations { + if o.Name == org { + return []*scm.OrganizationPendingInvite{{ + ID: 123, + Login: "fred", + InviterLogin: "charles", + }}, nil, nil + } + } + return nil, nil, scm.ErrNotFound +} + +func (s *organizationService) ListMemberships(ctx context.Context, opts scm.ListOptions) ([]*scm.Membership, *scm.Response, error) { + + return []*scm.Membership{ + { + OrganizationName: "test-org1", + State: "active", + Role: "admin", + }, + { + OrganizationName: "test-org2", + State: "pending", + Role: "member", + }, + }, nil, nil + +} + +func (s *organizationService) AcceptOrganizationInvitation(_ context.Context, org string) (*scm.Response, error) { + for _, o := range s.data.Organizations { + if o.Name == org { + return nil, nil + } + } + return nil, scm.ErrNotFound +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/pr.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/pr.go index aaa6508bb..4956ae461 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/pr.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/pr.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "regexp" + "strings" "github.com/jenkins-x/go-scm/scm" "k8s.io/apimachinery/pkg/util/sets" @@ -20,9 +21,6 @@ func (s *pullService) Find(ctx context.Context, repo string, number int) (*scm.P if !exists { return nil, nil, fmt.Errorf("Pull request number %d does not exit", number) } - if labels, _, err := s.client.Issues.ListLabels(ctx, repo, number, scm.ListOptions{}); err == nil { - val.Labels = labels - } return val, nil, nil } @@ -30,8 +28,20 @@ func (s *pullService) FindComment(context.Context, string, int, int) (*scm.Comme panic("implement me") } -func (s *pullService) List(context.Context, string, scm.PullRequestListOptions) ([]*scm.PullRequest, *scm.Response, error) { - panic("implement me") +func (s *pullService) List(ctx context.Context, fullName string, opts scm.PullRequestListOptions) ([]*scm.PullRequest, *scm.Response, error) { + var answer []*scm.PullRequest + f := s.data + for _, pr := range f.PullRequests { + repo := pr.Repository() + fn := repo.FullName + if fn == "" { + fn = scm.Join(repo.Namespace, repo.Name) + } + if fn == fullName { + answer = append(answer, pr) + } + } + return answer, nil, nil } func (s *pullService) ListChanges(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Change, *scm.Response, error) { @@ -67,6 +77,22 @@ func (s *pullService) ListEvents(context.Context, string, int, scm.ListOptions) func (s *pullService) AddLabel(ctx context.Context, repo string, number int, label string) (*scm.Response, error) { f := s.data + pr := s.data.PullRequests[number] + if pr != nil { + found := false + for _, l := range pr.Labels { + if l.Name == label { + found = true + break + } + } + if !found { + pr.Labels = append(pr.Labels, &scm.Label{ + ID: int64(len(pr.Labels)), + Name: label, + }) + } + } labelString := fmt.Sprintf("%s#%d:%s", repo, number, label) if sets.NewString(f.PullRequestLabelsAdded...).Has(labelString) { return nil, fmt.Errorf("cannot add %v to %s/#%d", label, repo, number) @@ -151,7 +177,19 @@ func (s *pullService) EditComment(ctx context.Context, repo string, number int, } func (s *pullService) AssignIssue(ctx context.Context, repo string, number int, logins []string) (*scm.Response, error) { - panic("implement me") + f := s.data + var m scm.MissingUsers + for _, a := range logins { + if a == "not-in-the-org" { + m.Users = append(m.Users, a) + continue + } + f.AssigneesAdded = append(f.AssigneesAdded, fmt.Sprintf("%s#%d:%s", repo, number, a)) + } + if m.Users == nil { + return nil, nil + } + return nil, m } func (s *pullService) UnassignIssue(ctx context.Context, repo string, number int, logins []string) (*scm.Response, error) { @@ -166,15 +204,27 @@ func (s *pullService) UnrequestReview(ctx context.Context, repo string, number i return nil, scm.ErrNotSupported } -func (s *pullService) Create(ctx context.Context, repo string, input *scm.PullRequestInput) (*scm.PullRequest, *scm.Response, error) { +func (s *pullService) Create(_ context.Context, fullName string, input *scm.PullRequestInput) (*scm.PullRequest, *scm.Response, error) { f := s.data f.PullRequestID++ + namespace := "" + name := "" + paths := strings.SplitN(fullName, "/", 2) + if len(paths) > 1 { + namespace = paths[0] + name = paths[1] + } answer := &scm.PullRequest{ Number: f.PullRequestID, Title: input.Title, Body: input.Body, Base: scm.PullRequestBranch{ Ref: input.Base, + Repo: scm.Repository{ + Namespace: namespace, + Name: name, + FullName: fullName, + }, }, Head: scm.PullRequestBranch{ Ref: input.Head, @@ -184,3 +234,11 @@ func (s *pullService) Create(ctx context.Context, repo string, input *scm.PullRe f.PullRequests[f.PullRequestID] = answer return answer, nil, nil } + +func (s *pullService) SetMilestone(ctx context.Context, repo string, prID int, number int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *pullService) ClearMilestone(ctx context.Context, repo string, prID int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/release.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/release.go new file mode 100644 index 000000000..ca1383214 --- /dev/null +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/release.go @@ -0,0 +1,108 @@ +package fake + +import ( + "context" + "strconv" + + "github.com/jenkins-x/go-scm/scm" +) + +type releaseService struct { + client *wrapper + data *Data +} + +func (r *releaseService) Find(_ context.Context, repo string, number int) (*scm.Release, *scm.Response, error) { + release := r.releaseMap(repo)[number] + if release == nil { + return nil, nil, scm.ErrNotFound + } + return release, nil, nil +} + +func (r *releaseService) releaseMap(repo string) map[int]*scm.Release { + if r.data.Releases == nil { + r.data.Releases = map[string]map[int]*scm.Release{} + } + releaseMap := r.data.Releases[repo] + if releaseMap == nil { + releaseMap = map[int]*scm.Release{} + r.data.Releases[repo] = releaseMap + } + return releaseMap +} + +func (r *releaseService) FindByTag(_ context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) { + for _, rel := range r.releaseMap(repo) { + if rel.Tag == tag { + return rel, nil, nil + } + } + return nil, nil, scm.ErrNotFound +} + +func (r *releaseService) List(_ context.Context, repo string, options scm.ReleaseListOptions) ([]*scm.Release, *scm.Response, error) { + var answer []*scm.Release + for _, rel := range r.releaseMap(repo) { + answer = append(answer, rel) + } + if len(answer) == 0 { + return nil, nil, scm.ErrNotFound + } + return answer, nil, nil +} + +func (r *releaseService) Create(_ context.Context, repo string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + m := r.releaseMap(repo) + id := len(m) + release := &scm.Release{ + ID: id, + Title: input.Title, + Description: input.Description, + Link: "https://fake.git/" + repo + "/releases/release/" + strconv.Itoa(id), + Tag: input.Tag, + Commitish: input.Commitish, + Draft: input.Draft, + Prerelease: input.Prerelease, + } + m[id] = release + return release, nil, nil +} + +func (r *releaseService) Update(_ context.Context, repo string, number int, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + rel := r.releaseMap(repo)[number] + if rel == nil { + return nil, nil, scm.ErrNotFound + } + if input.Commitish != "" { + rel.Commitish = input.Commitish + } + if input.Description != "" { + rel.Description = input.Description + } + if input.Tag != "" { + rel.Tag = input.Tag + } + if input.Title != "" { + rel.Title = input.Title + } + rel.Draft = input.Draft + rel.Prerelease = input.Prerelease + return nil, nil, nil +} + +func (r *releaseService) UpdateByTag(ctx context.Context, repo string, tag string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + rel, _, _ := r.FindByTag(ctx, repo, tag) + return r.Update(ctx, repo, rel.ID, input) +} + +func (r *releaseService) Delete(_ context.Context, repo string, number int) (*scm.Response, error) { + m := r.releaseMap(repo) + delete(m, number) + return nil, nil +} + +func (r *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) { + rel, _, _ := r.FindByTag(ctx, repo, tag) + return r.Delete(ctx, repo, rel.ID) +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/repo.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/repo.go index e086027b5..fef168135 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/repo.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/repo.go @@ -72,6 +72,31 @@ func (s *repositoryService) AddCollaborator(ctx context.Context, repo, user, per m[user] = permission s.data.UserPermissions[repo] = m + + // lets add an invitation if the user isn't already in the repo... + if !alreadyExists { + id := int64(len(s.data.Invitations) + 1) + names := strings.SplitN(repo, "/", 2) + owner := "" + repoName := "" + if len(names) == 2 { + owner = names[0] + repoName = names[1] + } + s.data.Invitations = append(s.data.Invitations, &scm.Invitation{ + ID: id, + Repo: &scm.Repository{ + Namespace: owner, + Name: repoName, + FullName: repo, + }, + Invitee: &scm.User{}, + Inviter: &scm.User{}, + Permissions: permission, + Created: time.Now(), + }) + } + return true, alreadyExists, nil, nil } @@ -98,10 +123,10 @@ func (s *repositoryService) ListCollaborators(ctx context.Context, repo string, func (s *repositoryService) Find(ctx context.Context, fullName string) (*scm.Repository, *scm.Response, error) { for _, repo := range s.data.Repositories { if repo.FullName == fullName { - return repo, nil, nil + return repo, &scm.Response{Status: 200}, nil } } - return nil, nil, scm.ErrNotFound + return nil, &scm.Response{Status: 404}, scm.ErrNotFound } func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { @@ -150,6 +175,7 @@ func (s *repositoryService) ListHooks(ctx context.Context, fullName string, opts } func (s *repositoryService) CreateHook(ctx context.Context, fullName string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) { + /* #nosec */ hook := &scm.Hook{ ID: fmt.Sprintf("%d", rand.Int()), Name: input.Name, @@ -188,3 +214,7 @@ func (s *repositoryService) CreateStatus(ctx context.Context, repo string, ref s s.data.Statuses[ref] = statuses return status, nil, nil } + +func (s *repositoryService) Delete(context.Context, string) (*scm.Response, error) { + panic("implement me") +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/user.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/user.go index 7a6c122b5..e73c9561a 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/user.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/fake/user.go @@ -11,16 +11,24 @@ type userService struct { data *Data } -func (u *userService) Find(ctx context.Context) (*scm.User, *scm.Response, error) { - return &u.data.CurrentUser, nil, nil +func (s *userService) CreateToken(context.Context, string, string) (*scm.UserToken, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported } -func (u *userService) FindEmail(ctx context.Context) (string, *scm.Response, error) { - return u.data.CurrentUser.Email, nil, nil +func (s *userService) DeleteToken(context.Context, int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported } -func (u *userService) FindLogin(ctx context.Context, login string) (*scm.User, *scm.Response, error) { - for _, user := range u.data.Users { +func (s *userService) Find(ctx context.Context) (*scm.User, *scm.Response, error) { + return &s.data.CurrentUser, nil, nil +} + +func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, error) { + return s.data.CurrentUser.Email, nil, nil +} + +func (s *userService) FindLogin(ctx context.Context, login string) (*scm.User, *scm.Response, error) { + for _, user := range s.data.Users { if user.Login == login { return user, nil, nil } @@ -29,9 +37,20 @@ func (u *userService) FindLogin(ctx context.Context, login string) (*scm.User, * } func (s *userService) ListInvitations(context.Context) ([]*scm.Invitation, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + return s.data.Invitations, nil, nil } -func (s *userService) AcceptInvitation(context.Context, int64) (*scm.Response, error) { +func (s *userService) AcceptInvitation(_ context.Context, id int64) (*scm.Response, error) { + invitations := s.data.Invitations + for i, invite := range invitations { + if invite.ID == id { + remaining := invitations[0:i] + if i+1 < len(invitations) { + remaining = append(remaining, invitations[i+1:]...) + } + s.data.Invitations = remaining + return nil, nil + } + } return nil, scm.ErrNotSupported } diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/content.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/content.go index 7025c775d..345c39345 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/content.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/content.go @@ -6,8 +6,10 @@ package gitea import ( "context" + "encoding/base64" "strings" + "code.gitea.io/sdk/gitea" "github.com/jenkins-x/go-scm/scm" ) @@ -21,25 +23,97 @@ func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm ref = strings.TrimPrefix(ref, "refs/heads/") ref = strings.TrimPrefix(ref, "refs/tags/") - out, err := s.client.GiteaClient.GetFile(namespace, name, ref, path) + out, resp, err := s.client.GiteaClient.GetContents(namespace, name, ref, path) + if err != nil { + return nil, toSCMResponse(resp), err + } + raw, _ := base64.StdEncoding.DecodeString(*out.Content) + return &scm.Content{ Path: path, - Data: out, - }, nil, err + Data: []byte(raw), + Sha: out.SHA, + }, toSCMResponse(resp), err } func (s *contentService) List(ctx context.Context, repo, path, ref string) ([]*scm.FileEntry, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + namespace, name := scm.Split(repo) + + ref = strings.TrimPrefix(ref, "refs/heads/") + ref = strings.TrimPrefix(ref, "refs/tags/") + + path = strings.TrimPrefix(path, "/") + + c, resp, err := s.client.GiteaClient.ListContents(namespace, name, ref, path) + if err != nil { + return nil, toSCMResponse(resp), err + } + return convertEntryList(c), toSCMResponse(resp), err + } func (s *contentService) Create(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { - return nil, scm.ErrNotSupported + + namespace, name := scm.Split(repo) + path = strings.TrimPrefix(path, "/") + + content := base64.StdEncoding.EncodeToString(params.Data) + + o := gitea.CreateFileOptions{ + FileOptions: gitea.FileOptions{ + Message: params.Message, + BranchName: params.Branch, + }, + Content: content, + } + + _, resp, err := s.client.GiteaClient.CreateFile(namespace, name, path, o) + return toSCMResponse(resp), err } func (s *contentService) Update(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { - return nil, scm.ErrNotSupported + + namespace, name := scm.Split(repo) + path = strings.TrimPrefix(path, "/") + + content := base64.StdEncoding.EncodeToString(params.Data) + + o := gitea.UpdateFileOptions{ + FileOptions: gitea.FileOptions{ + Message: params.Message, + BranchName: params.Branch, + }, + Content: content, + SHA: params.Sha, + } + + _, resp, err := s.client.GiteaClient.UpdateFile(namespace, name, path, o) + return toSCMResponse(resp), err } func (s *contentService) Delete(ctx context.Context, repo, path, ref string) (*scm.Response, error) { return nil, scm.ErrNotSupported } + +func convertEntryList(out []*gitea.ContentsResponse) []*scm.FileEntry { + answer := make([]*scm.FileEntry, 0, len(out)) + for _, o := range out { + answer = append(answer, convertEntry(o)) + } + return answer +} + +func convertEntry(from *gitea.ContentsResponse) *scm.FileEntry { + link := "" + if from.DownloadURL != nil { + link = *from.DownloadURL + } + return &scm.FileEntry{ + Name: from.Name, + Path: from.Path, + Type: from.Type, + Size: int(from.Size), + Sha: from.SHA, + Link: link, + } +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/git.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/git.go index 0fe7eb6d3..1fa62686d 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/git.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/git.go @@ -5,10 +5,14 @@ package gitea import ( - "code.gitea.io/sdk/gitea" "context" + "errors" + "fmt" + "strings" "time" + "code.gitea.io/sdk/gitea" + "github.com/jenkins-x/go-scm/scm" ) @@ -19,11 +23,17 @@ type gitService struct { func (s *gitService) FindRef(ctx context.Context, repo, ref string) (string, *scm.Response, error) { namespace, name := scm.Split(repo) - out, err := s.client.GiteaClient.GetRepoRef(namespace, name, ref) - if err != nil || out.Object == nil { - return "", nil, err + out, giteaResp, err := s.client.GiteaClient.GetRepoRefs(namespace, name, ref) + resp := toSCMResponse(giteaResp) + if err != nil { + return "", resp, err } - return out.Object.SHA, nil, nil + for _, r := range out { + if r.Object != nil { + return r.Object.SHA, resp, nil + } + } + return "", resp, fmt.Errorf("no match found for ref %s", ref) } func (s *gitService) CreateRef(ctx context.Context, repo, ref, sha string) (*scm.Reference, *scm.Response, error) { @@ -31,43 +41,69 @@ func (s *gitService) CreateRef(ctx context.Context, repo, ref, sha string) (*scm } func (s *gitService) DeleteRef(ctx context.Context, repo, ref string) (*scm.Response, error) { - return nil, scm.ErrNotSupported + namespace, name := scm.Split(repo) + if strings.HasPrefix(ref, "heads/") { + ref = strings.TrimPrefix(ref, "heads/") + } + out, giteaResp, err := s.client.GiteaClient.DeleteRepoBranch(namespace, name, ref) + resp := toSCMResponse(giteaResp) + if !out { + return resp, errors.New("Failed to delete branch") + } + return resp, err } func (s *gitService) FindBranch(ctx context.Context, repo, branchName string) (*scm.Reference, *scm.Response, error) { namespace, name := scm.Split(repo) - out, err := s.client.GiteaClient.GetRepoBranch(namespace, name, branchName) - return convertBranch(out), nil, err + out, resp, err := s.client.GiteaClient.GetRepoBranch(namespace, name, branchName) + return convertBranch(out), toSCMResponse(resp), err } func (s *gitService) FindCommit(ctx context.Context, repo, ref string) (*scm.Commit, *scm.Response, error) { namespace, name := scm.Split(repo) - out, err := s.client.GiteaClient.GetSingleCommit(namespace, name, ref) - return convertCommit(out), nil, err + out, resp, err := s.client.GiteaClient.GetSingleCommit(namespace, name, ref) + return convertCommit(out), toSCMResponse(resp), err } func (s *gitService) FindTag(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { return nil, nil, scm.ErrNotSupported } -func (s *gitService) ListBranches(ctx context.Context, repo string, _ scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { +func (s *gitService) ListBranches(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { namespace, name := scm.Split(repo) - out, err := s.client.GiteaClient.ListRepoBranches(namespace, name, gitea.ListRepoBranchesOptions{}) - return convertBranchList(out), nil, err + out, resp, err := s.client.GiteaClient.ListRepoBranches(namespace, name, gitea.ListRepoBranchesOptions{ListOptions: toGiteaListOptions(opts)}) + return convertBranchList(out), toSCMResponse(resp), err } -func (s *gitService) ListCommits(ctx context.Context, repo string, _ scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported +func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { + namespace, name := scm.Split(repo) + + listOpts := gitea.ListCommitOptions{ + ListOptions: gitea.ListOptions{ + Page: opts.Page, + PageSize: opts.Size, + }, + SHA: opts.Sha, + } + out, resp, err := s.client.GiteaClient.ListRepoCommits(namespace, name, listOpts) + return convertCommitList(out), toSCMResponse(resp), err } -func (s *gitService) ListTags(ctx context.Context, repo string, _ scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported +func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { + namespace, name := scm.Split(repo) + + out, resp, err := s.client.GiteaClient.ListRepoTags(namespace, name, gitea.ListRepoTagsOptions{ListOptions: toGiteaListOptions(opts)}) + return convertTagList(out), toSCMResponse(resp), err } func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { return nil, nil, scm.ErrNotSupported } +func (s *gitService) CompareCommits(ctx context.Context, repo, ref1, ref2 string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + // // native data structures // @@ -115,6 +151,33 @@ func convertBranch(src *gitea.Branch) *scm.Reference { } } +func convertTagList(src []*gitea.Tag) []*scm.Reference { + dst := []*scm.Reference{} + for _, v := range src { + dst = append(dst, convertTag(v)) + } + return dst +} + +func convertTag(src *gitea.Tag) *scm.Reference { + if src == nil || src.Commit == nil { + return nil + } + return &scm.Reference{ + Name: scm.TrimRef(src.Name), + Path: scm.ExpandRef(src.Name, "refs/tags/"), + Sha: src.Commit.SHA, + } +} + +func convertCommitList(src []*gitea.Commit) []*scm.Commit { + dst := []*scm.Commit{} + for _, v := range src { + dst = append(dst, convertCommit(v)) + } + return dst +} + func convertCommit(src *gitea.Commit) *scm.Commit { if src == nil || src.RepoCommit == nil { return nil diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/gitea.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/gitea.go index 5f84e17b9..f82458431 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/gitea.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/gitea.go @@ -19,12 +19,50 @@ import ( "github.com/jenkins-x/go-scm/scm" ) +// NewWebHookService creates a new instance of the webhook service without the rest of the client func NewWebHookService() scm.WebhookService { return &webhookService{nil} } -// New returns a new Gitea API client. +// New returns a new Gitea API client without a token set func New(uri string) (*scm.Client, error) { + return NewWithToken(uri, "") +} + +// NewWithToken returns a new Gitea API client with the token set. +func NewWithToken(uri string, token string) (*scm.Client, error) { + base, err := url.Parse(uri) + if err != nil { + return nil, err + } + if !strings.HasSuffix(base.Path, "/") { + base.Path = base.Path + "/" + } + client := &wrapper{Client: new(scm.Client)} + client.GiteaClient, err = gitea.NewClient(base.String(), gitea.SetToken(token)) + + if err != nil { + return nil, err + } + client.BaseURL = base + // initialize services + client.Driver = scm.DriverGitea + client.Contents = &contentService{client} + client.Git = &gitService{client} + client.Issues = &issueService{client} + client.Milestones = &milestoneService{client} + client.Organizations = &organizationService{client} + client.PullRequests = &pullService{&issueService{client}} + client.Repositories = &repositoryService{client} + client.Reviews = &reviewService{client} + client.Releases = &releaseService{client} + client.Users = &userService{client} + client.Webhooks = &webhookService{client} + return client.Client, nil +} + +// NewWithBasicAuth returns a new Gitea API client with the basic auth set. +func NewWithBasicAuth(uri string, user, password string) (*scm.Client, error) { base, err := url.Parse(uri) if err != nil { return nil, err @@ -32,18 +70,19 @@ func New(uri string) (*scm.Client, error) { if !strings.HasSuffix(base.Path, "/") { base.Path = base.Path + "/" } - client := &wrapper{ - Client: &scm.Client{ - Client: &http.Client{}, - }, + client := &wrapper{Client: new(scm.Client)} + client.GiteaClient, err = gitea.NewClient(base.String(), gitea.SetBasicAuth(user, password)) + + if err != nil { + return nil, err } - client.GiteaClient = gitea.NewClientWithHTTP(base.String(), client.Client.Client) client.BaseURL = base // initialize services client.Driver = scm.DriverGitea client.Contents = &contentService{client} client.Git = &gitService{client} client.Issues = &issueService{client} + client.Milestones = &milestoneService{client} client.Organizations = &organizationService{client} client.PullRequests = &pullService{&issueService{client}} client.Repositories = &repositoryService{client} @@ -108,3 +147,25 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface // the json response. return res, json.NewDecoder(res.Body).Decode(out) } + +// toSCMResponse creates a new Response for the provided +// http.Response. r must not be nil. +func toSCMResponse(r *gitea.Response) *scm.Response { + if r == nil { + return nil + } + res := &scm.Response{ + Status: r.StatusCode, + Header: r.Header, + Body: r.Body, + } + res.PopulatePageValues() + return res +} + +func toGiteaListOptions(in scm.ListOptions) gitea.ListOptions { + return gitea.ListOptions{ + Page: in.Page, + PageSize: in.Size, + } +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/issue.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/issue.go index 64e2f2edc..66ae581ce 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/issue.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/issue.go @@ -5,25 +5,13 @@ package gitea import ( - "code.gitea.io/sdk/gitea" "context" "fmt" - "github.com/pkg/errors" - "k8s.io/apimachinery/pkg/util/sets" - "time" + "code.gitea.io/sdk/gitea" "github.com/jenkins-x/go-scm/scm" -) - -type stateType string - -const ( - // stateOpen pr/issue is opend - stateOpen stateType = "open" - // stateClosed pr/issue is closed - stateClosed stateType = "closed" - // stateAll is all - stateAll stateType = "all" + "github.com/pkg/errors" + "k8s.io/apimachinery/pkg/util/sets" ) type issueService struct { @@ -53,8 +41,8 @@ func (s *issueService) AssignIssue(ctx context.Context, repo string, number int, Title: issue.Title, Assignees: assignees.List(), } - _, err = s.client.GiteaClient.EditIssue(namespace, name, int64(number), in) - return nil, err + _, giteaResp, err := s.client.GiteaClient.EditIssue(namespace, name, int64(number), in) + return toSCMResponse(giteaResp), err } func (s *issueService) UnassignIssue(ctx context.Context, repo string, number int, logins []string) (*scm.Response, error) { @@ -76,26 +64,39 @@ func (s *issueService) UnassignIssue(ctx context.Context, repo string, number in Title: issue.Title, Assignees: assignees.List(), } - _, err = s.client.GiteaClient.EditIssue(namespace, name, int64(number), in) - return nil, err + _, giteaResp, err := s.client.GiteaClient.EditIssue(namespace, name, int64(number), in) + return toSCMResponse(giteaResp), err } func (s *issueService) ListEvents(context.Context, string, int, scm.ListOptions) ([]*scm.ListedIssueEvent, *scm.Response, error) { return nil, nil, scm.ErrNotSupported } -func (s *issueService) ListLabels(ctx context.Context, repo string, number int, _ scm.ListOptions) ([]*scm.Label, *scm.Response, error) { +func (s *issueService) ListLabels(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Label, *scm.Response, error) { namespace, name := scm.Split(repo) - out, err := s.client.GiteaClient.GetIssueLabels(namespace, name, int64(number), gitea.ListLabelsOptions{}) - return convertGiteaLabels(out), nil, err + out, resp, err := s.client.GiteaClient.GetIssueLabels(namespace, name, int64(number), gitea.ListLabelsOptions{ListOptions: toGiteaListOptions(opts)}) + return convertLabels(out), toSCMResponse(resp), err } func (s *issueService) lookupLabel(ctx context.Context, repo string, lbl string) (int64, *scm.Response, error) { var labelID int64 labelID = -1 - repoLabels, res, err := s.client.Repositories.ListLabels(ctx, repo, scm.ListOptions{}) - if err != nil { - return labelID, res, errors.Wrapf(err, "listing labels in repository %s", repo) + var repoLabels []*scm.Label + var res *scm.Response + var labels []*scm.Label + var err error + firstRun := false + opts := scm.ListOptions{ + Page: 1, + } + for !firstRun || (res != nil && opts.Page <= res.Page.Last) { + labels, res, err = s.client.Repositories.ListLabels(ctx, repo, opts) + if err != nil { + return labelID, res, err + } + firstRun = true + repoLabels = append(repoLabels, labels...) + opts.Page++ } for _, l := range repoLabels { if l.Name == lbl { @@ -119,16 +120,16 @@ func (s *issueService) AddLabel(ctx context.Context, repo string, number int, lb Description: "", Name: lbl, } - newLabel, err := s.client.GiteaClient.CreateLabel(namespace, name, lblInput) + newLabel, giteaResp, err := s.client.GiteaClient.CreateLabel(namespace, name, lblInput) if err != nil { - return nil, errors.Wrapf(err, "failed to create label %s in repository %s", lbl, repo) + return toSCMResponse(giteaResp), errors.Wrapf(err, "failed to create label %s in repository %s", lbl, repo) } labelID = newLabel.ID } in := gitea.IssueLabelsOption{Labels: []int64{labelID}} - _, err = s.client.GiteaClient.AddIssueLabels(namespace, name, int64(number), in) - return nil, err + _, giteaResp, err := s.client.GiteaClient.AddIssueLabels(namespace, name, int64(number), in) + return toSCMResponse(giteaResp), err } func (s *issueService) DeleteLabel(ctx context.Context, repo string, number int, lbl string) (*scm.Response, error) { @@ -137,24 +138,37 @@ func (s *issueService) DeleteLabel(ctx context.Context, repo string, number int, return res, err } if labelID == -1 { - return nil, nil + return res, nil } namespace, name := scm.Split(repo) - err = s.client.GiteaClient.DeleteIssueLabel(namespace, name, int64(number), labelID) - return nil, err + giteaResp, err := s.client.GiteaClient.DeleteIssueLabel(namespace, name, int64(number), labelID) + return toSCMResponse(giteaResp), err } func (s *issueService) Find(ctx context.Context, repo string, number int) (*scm.Issue, *scm.Response, error) { namespace, name := scm.Split(repo) - out, err := s.client.GiteaClient.GetIssue(namespace, name, int64(number)) - return convertGiteaIssue(out), nil, err + out, resp, err := s.client.GiteaClient.GetIssue(namespace, name, int64(number)) + return convertIssue(out), toSCMResponse(resp), err } func (s *issueService) FindComment(ctx context.Context, repo string, index, id int) (*scm.Comment, *scm.Response, error) { - comments, res, err := s.ListComments(ctx, repo, index, scm.ListOptions{}) - if err != nil { - return nil, res, err + var comments []*scm.Comment + var res *scm.Response + var commentsPage []*scm.Comment + var err error + firstRun := false + opts := scm.ListOptions{ + Page: 1, + } + for !firstRun || (res != nil && opts.Page <= res.Page.Last) { + commentsPage, res, err = s.ListComments(ctx, repo, index, opts) + if err != nil { + return nil, res, err + } + firstRun = true + comments = append(comments, commentsPage...) + opts.Page++ } for _, comment := range comments { if comment.ID == id { @@ -164,19 +178,28 @@ func (s *issueService) FindComment(ctx context.Context, repo string, index, id i return nil, res, nil } -func (s *issueService) List(ctx context.Context, repo string, _ scm.IssueListOptions) ([]*scm.Issue, *scm.Response, error) { +func (s *issueService) List(ctx context.Context, repo string, opts scm.IssueListOptions) ([]*scm.Issue, *scm.Response, error) { namespace, name := scm.Split(repo) in := gitea.ListIssueOption{ + ListOptions: gitea.ListOptions{ + Page: opts.Page, + PageSize: opts.Size, + }, Type: gitea.IssueTypeIssue, } - out, err := s.client.GiteaClient.ListRepoIssues(namespace, name, in) - return convertIssueList(out), nil, err + if opts.Open && !opts.Closed { + in.State = gitea.StateOpen + } else if opts.Closed && !opts.Open { + in.State = gitea.StateClosed + } + out, resp, err := s.client.GiteaClient.ListRepoIssues(namespace, name, in) + return convertIssueList(out), toSCMResponse(resp), err } -func (s *issueService) ListComments(ctx context.Context, repo string, index int, _ scm.ListOptions) ([]*scm.Comment, *scm.Response, error) { +func (s *issueService) ListComments(ctx context.Context, repo string, index int, opts scm.ListOptions) ([]*scm.Comment, *scm.Response, error) { namespace, name := scm.Split(repo) - out, err := s.client.GiteaClient.ListIssueComments(namespace, name, int64(index), gitea.ListIssueCommentOptions{}) - return convertIssueCommentList(out), nil, err + out, resp, err := s.client.GiteaClient.ListIssueComments(namespace, name, int64(index), gitea.ListIssueCommentOptions{ListOptions: toGiteaListOptions(opts)}) + return convertIssueCommentList(out), toSCMResponse(resp), err } func (s *issueService) Create(ctx context.Context, repo string, input *scm.IssueInput) (*scm.Issue, *scm.Response, error) { @@ -186,27 +209,28 @@ func (s *issueService) Create(ctx context.Context, repo string, input *scm.Issue Title: input.Title, Body: input.Body, } - out, err := s.client.GiteaClient.CreateIssue(namespace, name, in) - return convertGiteaIssue(out), nil, err + out, resp, err := s.client.GiteaClient.CreateIssue(namespace, name, in) + return convertIssue(out), toSCMResponse(resp), err } func (s *issueService) CreateComment(ctx context.Context, repo string, index int, input *scm.CommentInput) (*scm.Comment, *scm.Response, error) { namespace, name := scm.Split(repo) in := gitea.CreateIssueCommentOption{Body: input.Body} - out, err := s.client.GiteaClient.CreateIssueComment(namespace, name, int64(index), in) - return convertGiteaIssueComment(out), nil, err + out, resp, err := s.client.GiteaClient.CreateIssueComment(namespace, name, int64(index), in) + return convertIssueComment(out), toSCMResponse(resp), err } func (s *issueService) DeleteComment(ctx context.Context, repo string, index, id int) (*scm.Response, error) { namespace, name := scm.Split(repo) - return nil, s.client.GiteaClient.DeleteIssueComment(namespace, name, int64(id)) + resp, err := s.client.GiteaClient.DeleteIssueComment(namespace, name, int64(id)) + return toSCMResponse(resp), err } func (s *issueService) EditComment(ctx context.Context, repo string, number int, id int, input *scm.CommentInput) (*scm.Comment, *scm.Response, error) { namespace, name := scm.Split(repo) in := gitea.EditIssueCommentOption{Body: input.Body} - out, err := s.client.GiteaClient.EditIssueComment(namespace, name, int64(id), in) - return convertGiteaIssueComment(out), nil, err + out, resp, err := s.client.GiteaClient.EditIssueComment(namespace, name, int64(id), in) + return convertIssueComment(out), toSCMResponse(resp), err } func (s *issueService) Close(ctx context.Context, repo string, number int) (*scm.Response, error) { @@ -215,8 +239,8 @@ func (s *issueService) Close(ctx context.Context, repo string, number int) (*scm in := gitea.EditIssueOption{ State: &closed, } - _, err := s.client.GiteaClient.EditIssue(namespace, name, int64(number), in) - return nil, err + _, resp, err := s.client.GiteaClient.EditIssue(namespace, name, int64(number), in) + return toSCMResponse(resp), err } func (s *issueService) Reopen(ctx context.Context, repo string, number int) (*scm.Response, error) { @@ -225,8 +249,8 @@ func (s *issueService) Reopen(ctx context.Context, repo string, number int) (*sc in := gitea.EditIssueOption{ State: &reopen, } - _, err := s.client.GiteaClient.EditIssue(namespace, name, int64(number), in) - return nil, err + _, resp, err := s.client.GiteaClient.EditIssue(namespace, name, int64(number), in) + return toSCMResponse(resp), err } func (s *issueService) Lock(ctx context.Context, repo string, number int) (*scm.Response, error) { @@ -237,82 +261,36 @@ func (s *issueService) Unlock(ctx context.Context, repo string, number int) (*sc return nil, scm.ErrNotSupported } -// -// native data structures -// - -type label struct { - ID int64 `json:"id"` - Name string `json:"name"` - // example: 00aabb - Color string `json:"color"` - Description string `json:"description"` - URL string `json:"url"` +func (s *issueService) SetMilestone(ctx context.Context, repo string, issueID int, number int) (*scm.Response, error) { + namespace, name := scm.Split(repo) + num64 := int64(number) + in := gitea.EditIssueOption{ + Milestone: &num64, + } + _, resp, err := s.client.GiteaClient.EditIssue(namespace, name, int64(issueID), in) + return toSCMResponse(resp), err } -type closeReopenInput struct { - State stateType `json:"state"` +func (s *issueService) ClearMilestone(ctx context.Context, repo string, id int) (*scm.Response, error) { + namespace, name := scm.Split(repo) + in := gitea.EditIssueOption{} + _, resp, err := s.client.GiteaClient.EditIssue(namespace, name, int64(id), in) + return toSCMResponse(resp), err } -type ( - // gitea issue response object. - issue struct { - ID int `json:"id"` - Number int `json:"number"` - User user `json:"user"` - Title string `json:"title"` - Body string `json:"body"` - State stateType `json:"state"` - Labels []label `json:"labels"` - Comments int `json:"comments"` - Assignees []user `json:"assignees"` - Created time.Time `json:"created_at"` - Updated time.Time `json:"updated_at"` - PullRequest *struct { - Merged bool `json:"merged"` - MergedAt interface{} `json:"merged_at"` - } `json:"pull_request"` - } - - // gitea issue comment response object. - issueComment struct { - ID int `json:"id"` - HTMLURL string `json:"html_url"` - User user `json:"user"` - Body string `json:"body"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - } -) - // // native data structure conversion // -func convertIssue(from *issue) *scm.Issue { - return &scm.Issue{ - Number: from.Number, - Title: from.Title, - Body: from.Body, - Link: "", // TODO construct the link to the issue. - Closed: from.State == "closed", - Labels: convertLabels(from), - Author: *convertUser(&from.User), - Assignees: convertUsers(from.Assignees), - Created: from.Created, - Updated: from.Updated, - } -} - func convertIssueList(from []*gitea.Issue) []*scm.Issue { to := []*scm.Issue{} for _, v := range from { - to = append(to, convertGiteaIssue(v)) + to = append(to, convertIssue(v)) } return to } -func convertGiteaIssue(from *gitea.Issue) *scm.Issue { +func convertIssue(from *gitea.Issue) *scm.Issue { return &scm.Issue{ Number: int(from.Index), Title: from.Title, @@ -320,52 +298,34 @@ func convertGiteaIssue(from *gitea.Issue) *scm.Issue { Link: from.URL, Closed: from.State == gitea.StateClosed, Labels: convertIssueLabels(from), - Author: *convertGiteaUser(from.Poster), - Assignees: convertGiteaUsers(from.Assignees), + Author: *convertUser(from.Poster), + Assignees: convertUsers(from.Assignees), Created: from.Created, Updated: from.Updated, } } -func convertIssueComment(from *issueComment) *scm.Comment { - return &scm.Comment{ - ID: from.ID, - Body: from.Body, - Author: *convertUser(&from.User), - Created: from.CreatedAt, - Updated: from.UpdatedAt, - } -} - func convertIssueCommentList(from []*gitea.Comment) []*scm.Comment { to := []*scm.Comment{} for _, v := range from { - to = append(to, convertGiteaIssueComment(v)) + to = append(to, convertIssueComment(v)) } return to } -func convertGiteaIssueComment(from *gitea.Comment) *scm.Comment { +func convertIssueComment(from *gitea.Comment) *scm.Comment { if from == nil || from.Poster == nil { return nil } return &scm.Comment{ ID: int(from.ID), Body: from.Body, - Author: *convertGiteaUser(from.Poster), + Author: *convertUser(from.Poster), Created: from.Created, Updated: from.Updated, } } -func convertLabels(from *issue) []string { - var labels []string - for _, label := range from.Labels { - labels = append(labels, label.Name) - } - return labels -} - func convertIssueLabels(from *gitea.Issue) []string { var labels []string for _, label := range from.Labels { @@ -374,10 +334,11 @@ func convertIssueLabels(from *gitea.Issue) []string { return labels } -func convertGiteaLabels(from []*gitea.Label) []*scm.Label { +func convertLabels(from []*gitea.Label) []*scm.Label { var labels []*scm.Label for _, label := range from { labels = append(labels, &scm.Label{ + ID: label.ID, Name: label.Name, Description: label.Description, URL: label.URL, diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/milestone.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/milestone.go new file mode 100644 index 000000000..6633b158a --- /dev/null +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/milestone.go @@ -0,0 +1,104 @@ +package gitea + +import ( + "context" + + "code.gitea.io/sdk/gitea" + "github.com/jenkins-x/go-scm/scm" +) + +type milestoneService struct { + client *wrapper +} + +func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) { + namespace, name := scm.Split(repo) + out, resp, err := s.client.GiteaClient.GetMilestone(namespace, name, int64(id)) + return convertMilestone(out), toSCMResponse(resp), err +} + +func (s *milestoneService) List(ctx context.Context, repo string, opts scm.MilestoneListOptions) ([]*scm.Milestone, *scm.Response, error) { + namespace, name := scm.Split(repo) + in := gitea.ListMilestoneOption{ + ListOptions: gitea.ListOptions{ + Page: opts.Page, + PageSize: opts.Size, + }, + } + if opts.Closed && opts.Open { + in.State = gitea.StateAll + } else if opts.Closed { + in.State = gitea.StateClosed + } else if opts.Open { + in.State = gitea.StateOpen + } + out, resp, err := s.client.GiteaClient.ListRepoMilestones(namespace, name, in) + return convertMilestoneList(out), toSCMResponse(resp), err +} + +func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + namespace, name := scm.Split(repo) + in := gitea.CreateMilestoneOption{ + Title: input.Title, + Description: input.Description, + State: gitea.StateOpen, + Deadline: input.DueDate, + } + if input.State == "closed" { + in.State = gitea.StateClosed + } + out, resp, err := s.client.GiteaClient.CreateMilestone(namespace, name, in) + return convertMilestone(out), toSCMResponse(resp), err +} + +func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + namespace, name := scm.Split(repo) + resp, err := s.client.GiteaClient.DeleteMilestone(namespace, name, int64(id)) + return toSCMResponse(resp), err +} + +func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + namespace, name := scm.Split(repo) + in := gitea.EditMilestoneOption{} + stateOpen := gitea.StateOpen + stateClosed := gitea.StateClosed + if input.Title != "" { + in.Title = input.Title + } + switch input.State { + case "open": + in.State = &stateOpen + case "close", "closed": + in.State = &stateClosed + } + if input.Description != "" { + in.Description = &input.Description + } + if input.DueDate != nil { + in.Deadline = input.DueDate + } + out, resp, err := s.client.GiteaClient.EditMilestone(namespace, name, int64(id), in) + return convertMilestone(out), toSCMResponse(resp), err +} + +func convertMilestoneList(from []*gitea.Milestone) []*scm.Milestone { + var to []*scm.Milestone + for _, m := range from { + to = append(to, convertMilestone(m)) + } + return to +} + +func convertMilestone(from *gitea.Milestone) *scm.Milestone { + if from == nil || from.Deadline == nil { + return nil + } + return &scm.Milestone{ + Number: int(from.ID), + ID: int(from.ID), + Title: from.Title, + Description: from.Description, + State: string(from.State), + DueDate: from.Deadline, + } +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/org.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/org.go index 7f601bf48..b12299b3c 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/org.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/org.go @@ -5,8 +5,9 @@ package gitea import ( - "code.gitea.io/sdk/gitea" "context" + + "code.gitea.io/sdk/gitea" "github.com/jenkins-x/go-scm/scm" ) @@ -14,15 +15,48 @@ type organizationService struct { client *wrapper } +func (s *organizationService) Create(_ context.Context, org *scm.OrganizationInput) (*scm.Organization, *scm.Response, error) { + visibility := gitea.VisibleTypePublic + if org.Private { + visibility = gitea.VisibleTypePrivate + } + out, resp, err := s.client.GiteaClient.CreateOrg(gitea.CreateOrgOption{ + Name: org.Name, + FullName: org.Name, + Description: org.Description, + Website: org.Homepage, + Visibility: visibility, + }) + return convertOrg(out), toSCMResponse(resp), err +} + +func (s *organizationService) Delete(_ context.Context, org string) (*scm.Response, error) { + resp, err := s.client.GiteaClient.DeleteOrg(org) + return toSCMResponse(resp), err +} + func (s *organizationService) IsMember(ctx context.Context, org string, user string) (bool, *scm.Response, error) { - isMember, err := s.client.GiteaClient.CheckOrgMembership(org, user) - return isMember, nil, err + isMember, resp, err := s.client.GiteaClient.CheckOrgMembership(org, user) + return isMember, toSCMResponse(resp), err } func (s *organizationService) IsAdmin(ctx context.Context, org string, user string) (bool, *scm.Response, error) { - members, res, err := s.ListOrgMembers(ctx, org, scm.ListOptions{}) - if err != nil { - return false, res, err + var members []*scm.TeamMember + var res *scm.Response + var membersPage []*scm.TeamMember + var err error + firstRun := false + opts := scm.ListOptions{ + Page: 1, + } + for !firstRun || (res != nil && opts.Page <= res.Page.Last) { + membersPage, res, err = s.ListOrgMembers(ctx, org, opts) + if err != nil { + return false, res, err + } + firstRun = true + members = append(members, membersPage...) + opts.Page++ } for _, m := range members { if m.Login == user && m.IsAdmin { @@ -33,26 +67,42 @@ func (s *organizationService) IsAdmin(ctx context.Context, org string, user stri } func (s *organizationService) ListTeams(ctx context.Context, org string, ops scm.ListOptions) ([]*scm.Team, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + out, resp, err := s.client.GiteaClient.ListOrgTeams(org, gitea.ListTeamsOptions{ListOptions: toGiteaListOptions(ops)}) + return convertTeamList(out), toSCMResponse(resp), err } func (s *organizationService) ListTeamMembers(ctx context.Context, id int, role string, ops scm.ListOptions) ([]*scm.TeamMember, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + out, resp, err := s.client.GiteaClient.ListTeamMembers(int64(id), gitea.ListTeamMembersOptions{ + ListOptions: toGiteaListOptions(ops), + }) + return convertMemberList(out), toSCMResponse(resp), err } func (s *organizationService) ListOrgMembers(ctx context.Context, org string, ops scm.ListOptions) ([]*scm.TeamMember, *scm.Response, error) { - out, err := s.client.GiteaClient.ListOrgMembership(org, gitea.ListOrgMembershipOption{}) - return convertMemberList(out), nil, err + out, resp, err := s.client.GiteaClient.ListOrgMembership(org, gitea.ListOrgMembershipOption{ListOptions: toGiteaListOptions(ops)}) + return convertMemberList(out), toSCMResponse(resp), err } func (s *organizationService) Find(ctx context.Context, name string) (*scm.Organization, *scm.Response, error) { - out, err := s.client.GiteaClient.GetOrg(name) - return convertOrg(out), nil, err + out, resp, err := s.client.GiteaClient.GetOrg(name) + return convertOrg(out), toSCMResponse(resp), err +} + +func (s *organizationService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Organization, *scm.Response, error) { + out, resp, err := s.client.GiteaClient.ListMyOrgs(gitea.ListOrgsOptions{ListOptions: toGiteaListOptions(opts)}) + return convertOrgList(out), toSCMResponse(resp), err +} + +func (s *organizationService) ListPendingInvitations(ctx context.Context, org string, opts scm.ListOptions) ([]*scm.OrganizationPendingInvite, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *organizationService) AcceptOrganizationInvitation(ctx context.Context, org string) (*scm.Response, error) { + return nil, scm.ErrNotSupported } -func (s *organizationService) List(ctx context.Context, _ scm.ListOptions) ([]*scm.Organization, *scm.Response, error) { - out, err := s.client.GiteaClient.ListMyOrgs(gitea.ListOrgsOptions{}) - return convertOrgList(out), nil, err +func (s *organizationService) ListMemberships(ctx context.Context, opts scm.ListOptions) ([]*scm.Membership, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported } // @@ -91,3 +141,22 @@ func convertMember(from *gitea.User) *scm.TeamMember { IsAdmin: from.IsAdmin, } } + +func convertTeamList(from []*gitea.Team) []*scm.Team { + var to []*scm.Team + for _, v := range from { + to = append(to, convertTeam(v)) + } + return to +} + +func convertTeam(from *gitea.Team) *scm.Team { + if from == nil { + return nil + } + return &scm.Team{ + ID: int(from.ID), + Name: from.Name, + Description: from.Description, + } +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/pr.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/pr.go index 8b0fcc67c..b80a16bfc 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/pr.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/pr.go @@ -6,11 +6,10 @@ package gitea import ( "bytes" - "code.gitea.io/sdk/gitea" "context" "fmt" - "time" + "code.gitea.io/sdk/gitea" "github.com/bluekeyes/go-gitdiff/gitdiff" "github.com/jenkins-x/go-scm/scm" ) @@ -21,14 +20,25 @@ type pullService struct { func (s *pullService) Find(ctx context.Context, repo string, index int) (*scm.PullRequest, *scm.Response, error) { namespace, name := scm.Split(repo) - out, err := s.client.GiteaClient.GetPullRequest(namespace, name, int64(index)) - return convertPullRequest(out), nil, err + out, resp, err := s.client.GiteaClient.GetPullRequest(namespace, name, int64(index)) + return convertPullRequest(out), toSCMResponse(resp), err } func (s *pullService) List(ctx context.Context, repo string, opts scm.PullRequestListOptions) ([]*scm.PullRequest, *scm.Response, error) { namespace, name := scm.Split(repo) - out, err := s.client.GiteaClient.ListRepoPullRequests(namespace, name, gitea.ListPullRequestsOptions{}) - return convertPullRequests(out), nil, err + in := gitea.ListPullRequestsOptions{ + ListOptions: gitea.ListOptions{ + Page: opts.Page, + PageSize: opts.Size, + }, + } + if opts.Open && !opts.Closed { + in.State = gitea.StateOpen + } else if opts.Closed && !opts.Open { + in.State = gitea.StateClosed + } + out, resp, err := s.client.GiteaClient.ListRepoPullRequests(namespace, name, in) + return convertPullRequests(out), toSCMResponse(resp), err } // TODO: Maybe contribute to gitea/go-sdk with .patch function? @@ -75,8 +85,8 @@ func (s *pullService) Merge(ctx context.Context, repo string, index int, options in.Title = options.CommitTitle } - _, err := s.client.GiteaClient.MergePullRequest(namespace, name, int64(index), in) - return nil, err + _, resp, err := s.client.GiteaClient.MergePullRequest(namespace, name, int64(index), in) + return toSCMResponse(resp), err } func (s *pullService) Update(ctx context.Context, repo string, number int, input *scm.PullRequestInput) (*scm.PullRequest, *scm.Response, error) { @@ -86,8 +96,8 @@ func (s *pullService) Update(ctx context.Context, repo string, number int, input Body: input.Body, Base: input.Base, } - out, err := s.client.GiteaClient.EditPullRequest(namespace, name, int64(number), in) - return convertPullRequest(out), nil, err + out, resp, err := s.client.GiteaClient.EditPullRequest(namespace, name, int64(number), in) + return convertPullRequest(out), toSCMResponse(resp), err } func (s *pullService) Close(ctx context.Context, repo string, number int) (*scm.Response, error) { @@ -96,8 +106,8 @@ func (s *pullService) Close(ctx context.Context, repo string, number int) (*scm. in := gitea.EditPullRequestOption{ State: &closed, } - _, err := s.client.GiteaClient.EditPullRequest(namespace, name, int64(number), in) - return nil, err + _, resp, err := s.client.GiteaClient.EditPullRequest(namespace, name, int64(number), in) + return toSCMResponse(resp), err } func (s *pullService) Reopen(ctx context.Context, repo string, number int) (*scm.Response, error) { @@ -106,8 +116,8 @@ func (s *pullService) Reopen(ctx context.Context, repo string, number int) (*scm in := gitea.EditPullRequestOption{ State: &reopen, } - _, err := s.client.GiteaClient.EditPullRequest(namespace, name, int64(number), in) - return nil, err + _, resp, err := s.client.GiteaClient.EditPullRequest(namespace, name, int64(number), in) + return toSCMResponse(resp), err } func (s *pullService) Create(ctx context.Context, repo string, input *scm.PullRequestInput) (*scm.PullRequest, *scm.Response, error) { @@ -118,8 +128,8 @@ func (s *pullService) Create(ctx context.Context, repo string, input *scm.PullRe Title: input.Title, Body: input.Body, } - out, err := s.client.GiteaClient.CreatePullRequest(namespace, name, in) - return convertPullRequest(out), nil, err + out, resp, err := s.client.GiteaClient.CreatePullRequest(namespace, name, in) + return convertPullRequest(out), toSCMResponse(resp), err } func (s *pullService) RequestReview(ctx context.Context, repo string, number int, logins []string) (*scm.Response, error) { @@ -130,36 +140,6 @@ func (s *pullService) UnrequestReview(ctx context.Context, repo string, number i return s.UnassignIssue(ctx, repo, number, logins) } -// -// native data structures -// - -type pullRequest struct { - ID int `json:"id"` - Number int `json:"number"` - User user `json:"user"` - Title string `json:"title"` - Body string `json:"body"` - State string `json:"state"` - HeadBranch string `json:"head_branch"` - HeadRepo repository `json:"head_repo"` - Head reference `json:"head"` - BaseBranch string `json:"base_branch"` - BaseRepo repository `json:"base_repo"` - Base reference `json:"base"` - HTMLURL string `json:"html_url"` - Mergeable bool `json:"mergeable"` - Merged bool `json:"merged"` - Created time.Time `json:"created_at"` - Updated time.Time `json:"updated_at"` -} - -type reference struct { - Repo repository `json:"repo"` - Name string `json:"ref"` - Sha string `json:"sha"` -} - // // native data structure conversion // @@ -176,26 +156,33 @@ func convertPullRequest(src *gitea.PullRequest) *scm.PullRequest { if src == nil || src.Title == "" { return nil } - return &scm.PullRequest{ + pr := &scm.PullRequest{ Number: int(src.Index), Title: src.Title, Body: src.Body, + Labels: convertLabels(src.Labels), Sha: src.Head.Sha, + Ref: fmt.Sprintf("refs/pull/%d/head", src.Index), + State: string(src.State), Source: src.Head.Name, Target: src.Base.Name, - Head: *convertPullRequestBranch(src.Head), + Fork: src.Base.Repository.FullName, Base: *convertPullRequestBranch(src.Base), + Head: *convertPullRequestBranch(src.Head), + DiffLink: src.DiffURL, Link: src.HTMLURL, - Fork: src.Base.Repository.FullName, - Ref: fmt.Sprintf("refs/pull/%d/head", src.Index), Closed: src.State == gitea.StateClosed, - Author: *convertGiteaUser(src.Poster), - Labels: convertGiteaLabels(src.Labels), + Author: *convertUser(src.Poster), + Assignees: convertUsers(src.Assignees), Merged: src.HasMerged, Mergeable: src.Mergeable, Created: *src.Created, Updated: *src.Updated, } + if src.MergedCommitID != nil { + pr.MergeSha = *src.MergedCommitID + } + return pr } func convertPullRequestFromIssue(src *gitea.Issue) *scm.PullRequest { @@ -203,8 +190,11 @@ func convertPullRequestFromIssue(src *gitea.Issue) *scm.PullRequest { Number: int(src.Index), Title: src.Title, Body: src.Body, + Labels: convertLabels(src.Labels), Closed: src.State == gitea.StateClosed, - Author: *convertGiteaUser(src.Poster), + State: string(src.State), + Link: src.URL, + Author: *convertUser(src.Poster), Merged: src.PullRequest.HasMerged, Created: src.Created, Updated: src.Updated, @@ -215,7 +205,7 @@ func convertPullRequestBranch(src *gitea.PRBranchInfo) *scm.PullRequestBranch { return &scm.PullRequestBranch{ Ref: src.Ref, Sha: src.Sha, - Repo: *convertGiteaRepository(src.Repository), + Repo: *convertRepository(src.Repository), } } diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/release.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/release.go new file mode 100644 index 000000000..c5e131163 --- /dev/null +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/release.go @@ -0,0 +1,169 @@ +package gitea + +import ( + "context" + "fmt" + "net/url" + "strings" + + "code.gitea.io/sdk/gitea" + "github.com/jenkins-x/go-scm/scm" +) + +type releaseService struct { + client *wrapper +} + +func (s *releaseService) Find(ctx context.Context, repo string, id int) (*scm.Release, *scm.Response, error) { + namespace, name := scm.Split(repo) + out, resp, err := s.client.GiteaClient.GetRelease(namespace, name, int64(id)) + return convertRelease(out), toSCMResponse(resp), err +} + +func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) { + + namespace, name := scm.Split(repo) + + // newer versions of gitea have a GetReleaseByTag that doesn't 500 error + if err := s.client.GiteaClient.CheckServerVersionConstraint(">= 1.13.2"); err == nil { + out, resp, err := s.client.GiteaClient.GetReleaseByTag(namespace, name, tag) + if err == nil { + // There is a bug where a release that is a tag is returned - filter these out based on contents of the fields + // https://github.com/go-gitea/gitea/pull/14397 + if out != nil && out.Title == "" && out.Note == "" { + return nil, nil, scm.ErrNotFound + } + } + return convertRelease(out), toSCMResponse(resp), err + } + + // older gitea version a broken `GetReleaseByTag`, so use `ListReleases` and iterate over each page + // https://github.com/go-gitea/gitea/commit/5ee09d3c8161280c72be8b02cd7ea354c1f55331 + var releases []*gitea.Release + var err error + opts := scm.ReleaseListOptions{ + Page: 1, + Size: 100, + } + + scanPages := 1000 + for opts.Page <= scanPages { + releases, _, err = s.client.GiteaClient.ListReleases(namespace, name, gitea.ListReleasesOptions{ListOptions: releaseListOptionsToGiteaListOptions(opts)}) + if err != nil { + return nil, nil, err + } + if len(releases) == 0 { + // no more pages to scan, release was not found + return nil, nil, scm.ErrNotFound + } + for _, r := range releases { + if strings.ToLower(r.TagName) == strings.ToLower(tag) { + return convertRelease(r), nil, nil + } + } + opts.Page++ + } + return nil, nil, fmt.Errorf("Gave up scanning for release after %v pages, upgrade gitea to >= 1.13.2", scanPages) +} + +func (s *releaseService) List(ctx context.Context, repo string, opts scm.ReleaseListOptions) ([]*scm.Release, *scm.Response, error) { + namespace, name := scm.Split(repo) + out, resp, err := s.client.GiteaClient.ListReleases(namespace, name, gitea.ListReleasesOptions{ListOptions: releaseListOptionsToGiteaListOptions(opts)}) + return convertReleaseList(out), toSCMResponse(resp), err +} + +func (s *releaseService) Create(ctx context.Context, repo string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + namespace, name := scm.Split(repo) + out, resp, err := s.client.GiteaClient.CreateRelease(namespace, name, gitea.CreateReleaseOption{ + TagName: input.Tag, + Target: input.Commitish, + Title: input.Title, + Note: input.Description, + IsDraft: input.Draft, + IsPrerelease: input.Prerelease, + }) + return convertRelease(out), toSCMResponse(resp), err +} + +func (s *releaseService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + namespace, name := scm.Split(repo) + resp, err := s.client.GiteaClient.DeleteRelease(namespace, name, int64(id)) + return toSCMResponse(resp), err +} + +func (s *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) { + rel, _, err := s.FindByTag(ctx, repo, tag) + if err != nil { + return nil, err + } + return s.Delete(ctx, repo, rel.ID) +} + +func (s *releaseService) Update(ctx context.Context, repo string, id int, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + namespace, name := scm.Split(repo) + out, resp, err := s.client.GiteaClient.EditRelease(namespace, name, int64(id), gitea.EditReleaseOption{ + TagName: input.Tag, + Target: input.Commitish, + Title: input.Title, + Note: input.Description, + IsDraft: &input.Draft, + IsPrerelease: &input.Prerelease, + }) + return convertRelease(out), toSCMResponse(resp), err +} + +func (s *releaseService) UpdateByTag(ctx context.Context, repo string, tag string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + rel, _, err := s.FindByTag(ctx, repo, tag) + if err != nil { + return nil, nil, err + } + return s.Update(ctx, repo, rel.ID, input) +} + +func convertReleaseList(from []*gitea.Release) []*scm.Release { + var to []*scm.Release + for _, m := range from { + to = append(to, convertRelease(m)) + } + return to +} + +// ConvertAPIURLToHTMLURL converts an release API endpoint into a html endpoint +func ConvertAPIURLToHTMLURL(apiURL string, tagName string) string { + // "url": "https://try.gitea.com/api/v1/repos/octocat/Hello-World/123", + // "html_url": "https://try.gitea.com/octocat/Hello-World/releases/tag/v1.0.0", + // the url field is the API url, not the html url, so until go-sdk v0.13.3, build it ourselves + link, err := url.Parse(apiURL) + if err != nil { + return "" + } + + pathParts := strings.Split(link.Path, "/") + if len(pathParts) != 7 { + return "" + } + link.Path = fmt.Sprintf("/%s/%s/releases/tag/%s", pathParts[4], pathParts[5], tagName) + return link.String() + +} +func convertRelease(from *gitea.Release) *scm.Release { + + return &scm.Release{ + ID: int(from.ID), + Title: from.Title, + Description: from.Note, + // Link: from.HTMLURL, + Link: ConvertAPIURLToHTMLURL(from.URL, from.TagName), + Tag: from.TagName, + Commitish: from.Target, + Draft: from.IsDraft, + Prerelease: from.IsPrerelease, + } +} + +func releaseListOptionsToGiteaListOptions(in scm.ReleaseListOptions) gitea.ListOptions { + return gitea.ListOptions{ + Page: in.Page, + PageSize: in.Size, + } +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/repo.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/repo.go index 22ea42a5f..3f0563421 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/repo.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/repo.go @@ -5,12 +5,11 @@ package gitea import ( - "code.gitea.io/sdk/gitea" "context" "net/url" "strconv" - "time" + "code.gitea.io/sdk/gitea" "github.com/jenkins-x/go-scm/scm" ) @@ -21,6 +20,7 @@ type repositoryService struct { func (s *repositoryService) Create(_ context.Context, input *scm.RepositoryInput) (*scm.Repository, *scm.Response, error) { var out *gitea.Repository var err error + var resp *gitea.Response in := gitea.CreateRepoOption{ Name: input.Name, Description: input.Description, @@ -28,80 +28,100 @@ func (s *repositoryService) Create(_ context.Context, input *scm.RepositoryInput } if input.Namespace == "" { - out, err = s.client.GiteaClient.CreateRepo(in) + out, resp, err = s.client.GiteaClient.CreateRepo(in) } else { - out, err = s.client.GiteaClient.CreateOrgRepo(input.Namespace, in) + out, resp, err = s.client.GiteaClient.CreateOrgRepo(input.Namespace, in) } - return convertGiteaRepository(out), nil, err + return convertRepository(out), toSCMResponse(resp), err } -func (s *repositoryService) Fork(context.Context, *scm.RepositoryInput, string) (*scm.Repository, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported +func (s *repositoryService) Fork(ctx context.Context, input *scm.RepositoryInput, origRepo string) (*scm.Repository, *scm.Response, error) { + namespace, name := scm.Split(origRepo) + opts := gitea.CreateForkOption{Organization: &input.Namespace} + out, resp, err := s.client.GiteaClient.CreateFork(namespace, name, opts) + return convertRepository(out), toSCMResponse(resp), err } func (s *repositoryService) FindCombinedStatus(_ context.Context, repo, ref string) (*scm.CombinedStatus, *scm.Response, error) { namespace, name := scm.Split(repo) - out, err := s.client.GiteaClient.GetCombinedStatus(namespace, name, ref) + out, resp, err := s.client.GiteaClient.GetCombinedStatus(namespace, name, ref) if err != nil { - return nil, nil, err + return nil, toSCMResponse(resp), err } return &scm.CombinedStatus{ State: convertState(out.State), Sha: out.SHA, Statuses: convertStatusList(out.Statuses), - }, nil, nil + }, toSCMResponse(resp), nil } -func (s *repositoryService) FindUserPermission(_ context.Context, repo string, user string) (string, *scm.Response, error) { - namespace, name := scm.Split(repo) - members, err := s.client.GiteaClient.ListCollaborators(namespace, name, gitea.ListCollaboratorsOptions{}) - if err != nil { - return "", nil, err +func (s *repositoryService) FindUserPermission(ctx context.Context, repo string, user string) (string, *scm.Response, error) { + namespace, _ := scm.Split(repo) + if user == namespace { + return scm.AdminPermission, nil, nil + } + var members []scm.User + var res *scm.Response + var membersPage []scm.User + var err error + firstRun := false + opts := scm.ListOptions{ + Page: 1, + } + for !firstRun || (res != nil && opts.Page <= res.Page.Last) { + membersPage, res, err = s.ListCollaborators(ctx, repo, opts) + if err != nil { + return "", res, err + } + firstRun = true + members = append(members, membersPage...) + opts.Page++ } for _, m := range members { - if m.UserName == user { + if m.Login == user { if m.IsAdmin { - return scm.AdminPermission, nil, nil + return scm.AdminPermission, res, nil } - return scm.WritePermission, nil, nil + return scm.WritePermission, res, nil } } - return scm.NoPermission, nil, nil + return scm.NoPermission, res, nil } func (s *repositoryService) AddCollaborator(_ context.Context, repo, user, permission string) (bool, bool, *scm.Response, error) { namespace, name := scm.Split(repo) - opt := gitea.AddCollaboratorOption{Permission: &permission} - err := s.client.GiteaClient.AddCollaborator(namespace, name, user, opt) + giteaPerm := gitea.AccessMode(permission) + opt := gitea.AddCollaboratorOption{Permission: &giteaPerm} + resp, err := s.client.GiteaClient.AddCollaborator(namespace, name, user, opt) if err != nil { - return false, false, nil, err + return false, false, toSCMResponse(resp), err } - return true, false, nil, nil + return true, false, toSCMResponse(resp), nil } func (s *repositoryService) IsCollaborator(_ context.Context, repo, user string) (bool, *scm.Response, error) { namespace, name := scm.Split(repo) - isCollab, err := s.client.GiteaClient.IsCollaborator(namespace, name, user) - return isCollab, nil, err + isCollab, resp, err := s.client.GiteaClient.IsCollaborator(namespace, name, user) + return isCollab, toSCMResponse(resp), err } func (s *repositoryService) ListCollaborators(_ context.Context, repo string, ops scm.ListOptions) ([]scm.User, *scm.Response, error) { namespace, name := scm.Split(repo) - out, err := s.client.GiteaClient.ListCollaborators(namespace, name, gitea.ListCollaboratorsOptions{}) - return convertGiteaUsers(out), nil, err + out, resp, err := s.client.GiteaClient.ListCollaborators(namespace, name, gitea.ListCollaboratorsOptions{ListOptions: toGiteaListOptions(ops)}) + return convertUsers(out), toSCMResponse(resp), err } -func (s *repositoryService) ListLabels(_ context.Context, repo string, _ scm.ListOptions) ([]*scm.Label, *scm.Response, error) { +func (s *repositoryService) ListLabels(_ context.Context, repo string, opts scm.ListOptions) ([]*scm.Label, *scm.Response, error) { namespace, name := scm.Split(repo) - out, err := s.client.GiteaClient.ListRepoLabels(namespace, name, gitea.ListLabelsOptions{}) - return convertGiteaLabels(out), nil, err + out, resp, err := s.client.GiteaClient.ListRepoLabels(namespace, name, gitea.ListLabelsOptions{ListOptions: toGiteaListOptions(opts)}) + return convertLabels(out), toSCMResponse(resp), err } func (s *repositoryService) Find(_ context.Context, repo string) (*scm.Repository, *scm.Response, error) { namespace, name := scm.Split(repo) - out, err := s.client.GiteaClient.GetRepo(namespace, name) - return convertGiteaRepository(out), nil, err + out, resp, err := s.client.GiteaClient.GetRepo(namespace, name) + return convertRepository(out), toSCMResponse(resp), err } func (s *repositoryService) FindHook(_ context.Context, repo string, id string) (*scm.Hook, *scm.Response, error) { @@ -110,43 +130,43 @@ func (s *repositoryService) FindHook(_ context.Context, repo string, id string) if err != nil { return nil, nil, err } - out, err := s.client.GiteaClient.GetRepoHook(namespace, name, idInt) - return convertHook(out), nil, err + out, resp, err := s.client.GiteaClient.GetRepoHook(namespace, name, idInt) + return convertHook(out), toSCMResponse(resp), err } func (s *repositoryService) FindPerms(ctx context.Context, repo string) (*scm.Perm, *scm.Response, error) { - r, _, err := s.Find(ctx, repo) + r, resp, err := s.Find(ctx, repo) if err != nil || r == nil { - return nil, nil, err + return nil, resp, err } - return r.Perm, nil, err + return r.Perm, resp, err } -func (s *repositoryService) List(_ context.Context, _ scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { - out, err := s.client.GiteaClient.ListMyRepos(gitea.ListReposOptions{}) - return convertRepositoryList(out), nil, err +func (s *repositoryService) List(_ context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { + out, resp, err := s.client.GiteaClient.ListMyRepos(gitea.ListReposOptions{ListOptions: toGiteaListOptions(opts)}) + return convertRepositoryList(out), toSCMResponse(resp), err } func (s *repositoryService) ListOrganisation(_ context.Context, org string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { - out, err := s.client.GiteaClient.ListOrgRepos(org, gitea.ListOrgReposOptions{}) - return convertRepositoryList(out), nil, err + out, resp, err := s.client.GiteaClient.ListOrgRepos(org, gitea.ListOrgReposOptions{ListOptions: toGiteaListOptions(opts)}) + return convertRepositoryList(out), toSCMResponse(resp), err } func (s *repositoryService) ListUser(_ context.Context, username string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { - out, err := s.client.GiteaClient.ListUserRepos(username, gitea.ListReposOptions{}) - return convertRepositoryList(out), nil, err + out, resp, err := s.client.GiteaClient.ListUserRepos(username, gitea.ListReposOptions{ListOptions: toGiteaListOptions(opts)}) + return convertRepositoryList(out), toSCMResponse(resp), err } -func (s *repositoryService) ListHooks(_ context.Context, repo string, _ scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { +func (s *repositoryService) ListHooks(_ context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { namespace, name := scm.Split(repo) - out, err := s.client.GiteaClient.ListRepoHooks(namespace, name, gitea.ListHooksOptions{}) - return convertHookList(out), nil, err + out, resp, err := s.client.GiteaClient.ListRepoHooks(namespace, name, gitea.ListHooksOptions{ListOptions: toGiteaListOptions(opts)}) + return convertHookList(out), toSCMResponse(resp), err } -func (s *repositoryService) ListStatus(_ context.Context, repo string, ref string, _ scm.ListOptions) ([]*scm.Status, *scm.Response, error) { +func (s *repositoryService) ListStatus(_ context.Context, repo string, ref string, opts scm.ListOptions) ([]*scm.Status, *scm.Response, error) { namespace, name := scm.Split(repo) - out, err := s.client.GiteaClient.ListStatuses(namespace, name, ref, gitea.ListStatusesOption{}) - return convertStatusList(out), nil, err + out, resp, err := s.client.GiteaClient.ListStatuses(namespace, name, ref, gitea.ListStatusesOption{ListOptions: toGiteaListOptions(opts)}) + return convertStatusList(out), toSCMResponse(resp), err } func (s *repositoryService) CreateHook(_ context.Context, repo string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) { @@ -172,8 +192,8 @@ func (s *repositoryService) CreateHook(_ context.Context, repo string, input *sc ), Active: true, } - out, err := s.client.GiteaClient.CreateRepoHook(namespace, name, in) - return convertHook(out), nil, err + out, resp, err := s.client.GiteaClient.CreateRepoHook(namespace, name, in) + return convertHook(out), toSCMResponse(resp), err } func (s *repositoryService) CreateStatus(_ context.Context, repo string, ref string, input *scm.StatusInput) (*scm.Status, *scm.Response, error) { @@ -184,8 +204,8 @@ func (s *repositoryService) CreateStatus(_ context.Context, repo string, ref str Description: input.Desc, Context: input.Label, } - out, err := s.client.GiteaClient.CreateStatus(namespace, name, ref, in) - return convertStatus(out), nil, err + out, resp, err := s.client.GiteaClient.CreateStatus(namespace, name, ref, in) + return convertStatus(out), toSCMResponse(resp), err } func (s *repositoryService) DeleteHook(_ context.Context, repo string, id string) (*scm.Response, error) { @@ -194,39 +214,15 @@ func (s *repositoryService) DeleteHook(_ context.Context, repo string, id string if err != nil { return nil, err } - err = s.client.GiteaClient.DeleteRepoHook(namespace, name, idInt) - return nil, err + resp, err := s.client.GiteaClient.DeleteRepoHook(namespace, name, idInt) + return toSCMResponse(resp), err } -// -// native data structures -// - -type ( - // gitea repository resource. - repository struct { - ID int `json:"id"` - Owner user `json:"owner"` - Name string `json:"name"` - FullName string `json:"full_name"` - Private bool `json:"private"` - Fork bool `json:"fork"` - HTMLURL string `json:"html_url"` - SSHURL string `json:"ssh_url"` - CloneURL string `json:"clone_url"` - DefaultBranch string `json:"default_branch"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - Permissions perm `json:"permissions"` - } - - // gitea permissions details. - perm struct { - Admin bool `json:"admin"` - Push bool `json:"push"` - Pull bool `json:"pull"` - } -) +func (s *repositoryService) Delete(_ context.Context, repo string) (*scm.Response, error) { + namespace, name := scm.Split(repo) + resp, err := s.client.GiteaClient.DeleteRepo(namespace, name) + return toSCMResponse(resp), err +} // // native data structure conversion @@ -235,12 +231,12 @@ type ( func convertRepositoryList(src []*gitea.Repository) []*scm.Repository { var dst []*scm.Repository for _, v := range src { - dst = append(dst, convertGiteaRepository(v)) + dst = append(dst, convertRepository(v)) } return dst } -func convertGiteaRepository(src *gitea.Repository) *scm.Repository { +func convertRepository(src *gitea.Repository) *scm.Repository { if src == nil || src.Owner == nil { return nil } @@ -249,7 +245,7 @@ func convertGiteaRepository(src *gitea.Repository) *scm.Repository { Namespace: src.Owner.UserName, Name: src.Name, FullName: src.FullName, - Perm: convertGiteaPerm(src.Permissions), + Perm: convertPerm(src.Permissions), Branch: src.DefaultBranch, Private: src.Private, Clone: src.CloneURL, @@ -260,7 +256,7 @@ func convertGiteaRepository(src *gitea.Repository) *scm.Repository { } } -func convertGiteaPerm(src *gitea.Permission) *scm.Perm { +func convertPerm(src *gitea.Permission) *scm.Perm { if src == nil { return nil } @@ -271,28 +267,6 @@ func convertGiteaPerm(src *gitea.Permission) *scm.Perm { } } -func convertRepository(src *repository) *scm.Repository { - return &scm.Repository{ - ID: strconv.Itoa(src.ID), - Namespace: userLogin(&src.Owner), - Name: src.Name, - FullName: src.FullName, - Perm: convertPerm(src.Permissions), - Branch: src.DefaultBranch, - Private: src.Private, - Clone: src.CloneURL, - CloneSSH: src.SSHURL, - } -} - -func convertPerm(src perm) *scm.Perm { - return &scm.Perm{ - Push: src.Push, - Pull: src.Pull, - Admin: src.Admin, - } -} - func convertHookList(src []*gitea.Hook) []*scm.Hook { var dst []*scm.Hook for _, v := range src { @@ -315,6 +289,12 @@ func convertHookEvent(from scm.HookEvents) []string { if from.PullRequest { events = append(events, "pull_request") } + if from.Review { + events = append(events, "pull_request_review") + } + if from.ReviewComment { + events = append(events, "pull_request_review_comment") + } if from.Issue { events = append(events, "issues") } diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/review.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/review.go index b51b77334..1fa05fc74 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/review.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/review.go @@ -7,6 +7,7 @@ package gitea import ( "context" + "code.gitea.io/sdk/gitea" "github.com/jenkins-x/go-scm/scm" ) @@ -15,33 +16,136 @@ type reviewService struct { } func (s *reviewService) Find(ctx context.Context, repo string, number, id int) (*scm.Review, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + namespace, name := scm.Split(repo) + review, resp, err := s.client.GiteaClient.GetPullReview(namespace, name, int64(number), int64(id)) + return convertReview(review), toSCMResponse(resp), err } func (s *reviewService) List(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Review, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + namespace, name := scm.Split(repo) + reviews, resp, err := s.client.GiteaClient.ListPullReviews(namespace, name, int64(number), gitea.ListPullReviewsOptions{ListOptions: toGiteaListOptions(opts)}) + + return convertReviewList(reviews), toSCMResponse(resp), err } func (s *reviewService) Create(ctx context.Context, repo string, number int, input *scm.ReviewInput) (*scm.Review, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + namespace, name := scm.Split(repo) + + in := gitea.CreatePullReviewOptions{ + State: toGiteaState(input.Event), + Body: input.Body, + CommitID: input.Sha, + Comments: toCreatePullRequestComments(input.Comments), + } + review, resp, err := s.client.GiteaClient.CreatePullReview(namespace, name, int64(number), in) + return convertReview(review), toSCMResponse(resp), err } func (s *reviewService) Delete(ctx context.Context, repo string, number, id int) (*scm.Response, error) { - return nil, scm.ErrNotSupported + namespace, name := scm.Split(repo) + resp, err := s.client.GiteaClient.DeletePullReview(namespace, name, int64(number), int64(id)) + return toSCMResponse(resp), err } func (s *reviewService) ListComments(ctx context.Context, repo string, prID int, reviewID int, options scm.ListOptions) ([]*scm.ReviewComment, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + namespace, name := scm.Split(repo) + comments, resp, err := s.client.GiteaClient.ListPullReviewComments(namespace, name, int64(prID), int64(reviewID)) + return convertReviewCommentList(comments), toSCMResponse(resp), err } func (s *reviewService) Update(ctx context.Context, repo string, prID int, reviewID int, body string) (*scm.Review, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + namespace, name := scm.Split(repo) + in := gitea.SubmitPullReviewOptions{ + Body: body, + } + review, resp, err := s.client.GiteaClient.SubmitPullReview(namespace, name, int64(prID), int64(reviewID), in) + return convertReview(review), toSCMResponse(resp), err } func (s *reviewService) Submit(ctx context.Context, repo string, prID int, reviewID int, input *scm.ReviewSubmitInput) (*scm.Review, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + namespace, name := scm.Split(repo) + in := gitea.SubmitPullReviewOptions{ + State: toGiteaState(input.Event), + Body: input.Body, + } + review, resp, err := s.client.GiteaClient.SubmitPullReview(namespace, name, int64(prID), int64(reviewID), in) + return convertReview(review), toSCMResponse(resp), err } +// TODO: Figure out whether this actually is a _thing_ exactly in Gitea. I don't think it is. func (s *reviewService) Dismiss(ctx context.Context, repo string, prID int, reviewID int, msg string) (*scm.Review, *scm.Response, error) { return nil, nil, scm.ErrNotSupported } + +func convertReviewList(from []*gitea.PullReview) []*scm.Review { + to := []*scm.Review{} + for _, v := range from { + to = append(to, convertReview(v)) + } + return to +} + +func convertReview(src *gitea.PullReview) *scm.Review { + if src == nil || src.Reviewer == nil { + return nil + } + return &scm.Review{ + ID: int(src.ID), + Body: src.Body, + Sha: src.CommitID, + Link: src.HTMLURL, + State: string(src.State), + Author: *convertUser(src.Reviewer), + Created: src.Submitted, + } +} + +func convertReviewCommentList(src []*gitea.PullReviewComment) []*scm.ReviewComment { + var out []*scm.ReviewComment + for _, v := range src { + out = append(out, convertReviewComment(v)) + } + return out +} + +func convertReviewComment(src *gitea.PullReviewComment) *scm.ReviewComment { + return &scm.ReviewComment{ + ID: int(src.ID), + Body: src.Body, + Path: src.Path, + Sha: src.CommitID, + Line: int(src.LineNum), + Link: src.HTMLURL, + Author: *convertUser(src.Reviewer), + Created: src.Created, + Updated: src.Updated, + } +} +func toCreatePullRequestComments(src []*scm.ReviewCommentInput) []gitea.CreatePullReviewComment { + var out []gitea.CreatePullReviewComment + for _, c := range src { + out = append(out, gitea.CreatePullReviewComment{ + Path: c.Path, + Body: c.Body, + NewLineNum: int64(c.Line), + }) + } + return out +} + +func toGiteaState(src string) gitea.ReviewStateType { + switch src { + case "APPROVED": + return gitea.ReviewStateApproved + case "PENDING": + return gitea.ReviewStatePending + case "COMMENT": + return gitea.ReviewStateComment + case "REQUEST_CHANGES": + return gitea.ReviewStateRequestChanges + case "REQUEST_REVIEW": + return gitea.ReviewStateRequestReview + default: + return gitea.ReviewStateComment + } +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/user.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/user.go index 632c105e0..fc276277a 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/user.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/user.go @@ -5,8 +5,9 @@ package gitea import ( - "code.gitea.io/sdk/gitea" "context" + + "code.gitea.io/sdk/gitea" "github.com/jenkins-x/go-scm/scm" ) @@ -14,14 +15,33 @@ type userService struct { client *wrapper } +func (s *userService) CreateToken(_ context.Context, user string, name string) (*scm.UserToken, *scm.Response, error) { + out, resp, err := s.client.GiteaClient.CreateAccessToken(gitea.CreateAccessTokenOption{ + Name: name, + }) + if out == nil { + return nil, toSCMResponse(resp), err + } + token := &scm.UserToken{ + ID: out.ID, + Token: out.Token, + } + return token, toSCMResponse(resp), err +} + +func (s *userService) DeleteToken(_ context.Context, id int64) (*scm.Response, error) { + resp, err := s.client.GiteaClient.DeleteAccessToken(id) + return toSCMResponse(resp), err +} + func (s *userService) Find(ctx context.Context) (*scm.User, *scm.Response, error) { - out, err := s.client.GiteaClient.GetMyUserInfo() - return convertGiteaUser(out), nil, err + out, resp, err := s.client.GiteaClient.GetMyUserInfo() + return convertUser(out), toSCMResponse(resp), err } func (s *userService) FindLogin(ctx context.Context, login string) (*scm.User, *scm.Response, error) { - out, err := s.client.GiteaClient.GetUserInfo(login) - return convertGiteaUser(out), nil, err + out, resp, err := s.client.GiteaClient.GetUserInfo(login) + return convertUser(out), toSCMResponse(resp), err } func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, error) { @@ -40,27 +60,14 @@ func (s *userService) AcceptInvitation(context.Context, int64) (*scm.Response, e return nil, scm.ErrNotSupported } -// -// native data structures -// - -type user struct { - ID int `json:"id"` - Login string `json:"login"` - Username string `json:"username"` - Fullname string `json:"full_name"` - Email string `json:"email"` - Avatar string `json:"avatar_url"` -} - // // native data structure conversion // -func convertGiteaUsers(src []*gitea.User) []scm.User { +func convertUsers(src []*gitea.User) []scm.User { answer := []scm.User{} for _, u := range src { - user := convertGiteaUser(u) + user := convertUser(u) if user.Login != "" { answer = append(answer, *user) } @@ -71,21 +78,7 @@ func convertGiteaUsers(src []*gitea.User) []scm.User { return answer } -func convertUsers(src []user) []scm.User { - answer := []scm.User{} - for _, u := range src { - user := convertUser(&u) - if user.Login != "" { - answer = append(answer, *user) - } - } - if len(answer) == 0 { - return nil - } - return answer -} - -func convertGiteaUser(src *gitea.User) *scm.User { +func convertUser(src *gitea.User) *scm.User { if src == nil || src.UserName == "" { return nil } @@ -97,18 +90,3 @@ func convertGiteaUser(src *gitea.User) *scm.User { Avatar: src.AvatarURL, } } -func convertUser(src *user) *scm.User { - return &scm.User{ - Login: userLogin(src), - Avatar: src.Avatar, - Email: src.Email, - Name: src.Fullname, - } -} - -func userLogin(src *user) string { - if src.Username != "" { - return src.Username - } - return src.Login -} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/webhook.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/webhook.go index 2c0e75d45..652a3219c 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/webhook.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitea/webhook.go @@ -5,14 +5,14 @@ package gitea import ( - "code.gitea.io/sdk/gitea" "crypto/sha256" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" + "code.gitea.io/sdk/gitea" + "github.com/jenkins-x/go-scm/pkg/hmac" "github.com/jenkins-x/go-scm/scm" ) @@ -47,8 +47,10 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo hook, err = s.parseIssueCommentHook(data) case "pull_request": hook, err = s.parsePullRequestHook(data) + case "reviewed": + hook, err = s.parsePullRequestReviewHook(data) default: - return nil, scm.UnknownWebhook{event} + return nil, scm.UnknownWebhook{Event: event} } if err != nil { return nil, err @@ -103,7 +105,7 @@ func (s *webhookService) parseCreateHook(data []byte) (scm.Webhook, error) { case "branch": return convertBranchHook(dst, scm.ActionCreate), err default: - return nil, scm.UnknownWebhook{dst.RefType} + return nil, scm.UnknownWebhook{Event: dst.RefType} } } @@ -116,7 +118,7 @@ func (s *webhookService) parseDeleteHook(data []byte) (scm.Webhook, error) { case "branch": return convertBranchHook(dst, scm.ActionDelete), err default: - return nil, scm.UnknownWebhook{dst.RefType} + return nil, scm.UnknownWebhook{Event: dst.RefType} } } @@ -141,6 +143,12 @@ func (s *webhookService) parsePullRequestHook(data []byte) (scm.Webhook, error) return convertPullRequestHook(dst), err } +func (s *webhookService) parsePullRequestReviewHook(data []byte) (scm.Webhook, error) { + dst := new(pullRequestReviewHook) + err := json.Unmarshal(data, dst) + return convertPullRequestReviewHook(dst), err +} + // // native data structures // @@ -186,6 +194,22 @@ type ( Repository gitea.Repository `json:"repository"` Sender gitea.User `json:"sender"` } + + // gitea pull request review webhook payload + pullRequestReviewHook struct { + Action string `json:"action"` + Number int `json:"number"` + PullRequest gitea.PullRequest `json:"pull_request"` + Repository gitea.Repository `json:"repository"` + Sender gitea.User `json:"sender"` + Review pullRequestReviewPayload `json:"review"` + } + + // gitea pull request review webhook sub-payload + pullRequestReviewPayload struct { + Type string `json:"type"` + Content string `json:"content"` + } ) // @@ -199,8 +223,8 @@ func convertTagHook(dst *createHook, action scm.Action) *scm.TagHook { Name: dst.Ref, Sha: dst.Sha, }, - Repo: *convertGiteaRepository(&dst.Repository), - Sender: *convertGiteaUser(&dst.Sender), + Repo: *convertRepository(&dst.Repository), + Sender: *convertUser(&dst.Sender), } } @@ -210,83 +234,85 @@ func convertBranchHook(dst *createHook, action scm.Action) *scm.BranchHook { Ref: scm.Reference{ Name: dst.Ref, }, - Repo: *convertGiteaRepository(&dst.Repository), - Sender: *convertGiteaUser(&dst.Sender), + Repo: *convertRepository(&dst.Repository), + Sender: *convertUser(&dst.Sender), } } -func convertPushHook(dst *pushHook) *scm.PushHook { - if len(dst.Commits) > 0 { +func convertPushHook(src *pushHook) *scm.PushHook { + if len(src.Commits) > 0 { return &scm.PushHook{ - Ref: dst.Ref, + Ref: src.Ref, + Before: src.Before, + After: src.After, + Compare: src.Compare, Commit: scm.Commit{ - Sha: dst.After, - Message: dst.Commits[0].Message, - Link: dst.Compare, + Sha: src.After, + Message: src.Commits[0].Message, + Link: src.Compare, Author: scm.Signature{ - Login: dst.Commits[0].Author.Username, - Email: dst.Commits[0].Author.Email, - Name: dst.Commits[0].Author.Name, - Date: dst.Commits[0].Timestamp, + Login: src.Commits[0].Author.Username, + Email: src.Commits[0].Author.Email, + Name: src.Commits[0].Author.Name, + Date: src.Commits[0].Timestamp, }, Committer: scm.Signature{ - Login: dst.Commits[0].Committer.Username, - Email: dst.Commits[0].Committer.Email, - Name: dst.Commits[0].Committer.Name, - Date: dst.Commits[0].Timestamp, + Login: src.Commits[0].Committer.Username, + Email: src.Commits[0].Committer.Email, + Name: src.Commits[0].Committer.Name, + Date: src.Commits[0].Timestamp, }, }, - Repo: *convertGiteaRepository(&dst.Repository), - Sender: *convertGiteaUser(&dst.Sender), + Repo: *convertRepository(&src.Repository), + Sender: *convertUser(&src.Sender), } - } else { - return &scm.PushHook{ - Ref: dst.Ref, - Commit: scm.Commit{ - Sha: dst.After, - Link: dst.Compare, - Author: scm.Signature{ - Login: dst.Pusher.UserName, - Email: dst.Pusher.Email, - Name: dst.Pusher.FullName, - }, - Committer: scm.Signature{ - Login: dst.Pusher.UserName, - Email: dst.Pusher.Email, - Name: dst.Pusher.FullName, - }, + } + return &scm.PushHook{ + Ref: src.Ref, + Before: src.Before, + After: src.After, + Compare: src.Compare, + Commit: scm.Commit{ + Sha: src.After, + Link: src.Compare, + Author: scm.Signature{ + Login: src.Pusher.UserName, + Email: src.Pusher.Email, + Name: src.Pusher.FullName, }, - Repo: *convertGiteaRepository(&dst.Repository), - Sender: *convertGiteaUser(&dst.Sender), - } + Committer: scm.Signature{ + Login: src.Pusher.UserName, + Email: src.Pusher.Email, + Name: src.Pusher.FullName, + }, + }, + Repo: *convertRepository(&src.Repository), + Sender: *convertUser(&src.Sender), } } func convertPullRequestHook(dst *pullRequestHook) *scm.PullRequestHook { return &scm.PullRequestHook{ - Action: convertAction(dst.Action), - PullRequest: scm.PullRequest{ - Number: int(dst.PullRequest.Index), - Title: dst.PullRequest.Title, - Body: dst.PullRequest.Body, - Closed: dst.PullRequest.State == "closed", - Author: scm.User{ - Login: dst.PullRequest.Poster.UserName, - Email: dst.PullRequest.Poster.Email, - Avatar: dst.PullRequest.Poster.AvatarURL, - }, - Merged: dst.PullRequest.HasMerged, - // Created: nil, - // Updated: nil, - Source: dst.PullRequest.Head.Name, - Target: dst.PullRequest.Base.Name, - Fork: dst.PullRequest.Head.Repository.FullName, - Link: dst.PullRequest.HTMLURL, - Ref: fmt.Sprintf("refs/pull/%d/head", dst.PullRequest.Index), - Sha: dst.PullRequest.Head.Sha, - }, - Repo: *convertGiteaRepository(&dst.Repository), - Sender: *convertGiteaUser(&dst.Sender), + Action: convertAction(dst.Action), + PullRequest: *convertPullRequest(&dst.PullRequest), + Repo: *convertRepository(&dst.Repository), + Sender: *convertUser(&dst.Sender), + } +} + +func convertPullRequestReviewPayload(dst *pullRequestReviewHook) *scm.Review { + return &scm.Review{ + Body: dst.Review.Content, + Author: *convertUser(&dst.Sender), + } +} + +func convertPullRequestReviewHook(dst *pullRequestReviewHook) *scm.ReviewHook { + return &scm.ReviewHook{ + Action: convertReviewAction(dst.Review.Type), + PullRequest: *convertPullRequest(&dst.PullRequest), + Repo: *convertRepository(&dst.Repository), + Review: *convertPullRequestReviewPayload(dst), } } @@ -294,28 +320,41 @@ func convertPullRequestCommentHook(dst *issueHook) *scm.PullRequestCommentHook { return &scm.PullRequestCommentHook{ Action: convertAction(dst.Action), PullRequest: *convertPullRequestFromIssue(&dst.Issue), - Comment: *convertGiteaIssueComment(&dst.Comment), - Repo: *convertGiteaRepository(&dst.Repository), - Sender: *convertGiteaUser(&dst.Sender), + Comment: *convertIssueComment(&dst.Comment), + Repo: *convertRepository(&dst.Repository), + Sender: *convertUser(&dst.Sender), } } func convertIssueHook(dst *issueHook) *scm.IssueHook { return &scm.IssueHook{ Action: convertAction(dst.Action), - Issue: *convertGiteaIssue(&dst.Issue), - Repo: *convertGiteaRepository(&dst.Repository), - Sender: *convertGiteaUser(&dst.Sender), + Issue: *convertIssue(&dst.Issue), + Repo: *convertRepository(&dst.Repository), + Sender: *convertUser(&dst.Sender), } } func convertIssueCommentHook(dst *issueHook) *scm.IssueCommentHook { return &scm.IssueCommentHook{ Action: convertAction(dst.Action), - Issue: *convertGiteaIssue(&dst.Issue), - Comment: *convertGiteaIssueComment(&dst.Comment), - Repo: *convertGiteaRepository(&dst.Repository), - Sender: *convertGiteaUser(&dst.Sender), + Issue: *convertIssue(&dst.Issue), + Comment: *convertIssueComment(&dst.Comment), + Repo: *convertRepository(&dst.Repository), + Sender: *convertUser(&dst.Sender), + } +} + +func convertReviewAction(src string) (action scm.Action) { + switch src { + case "pull_request_review_approved": + return scm.ActionSubmitted + case "pull_request_review_comment": + return scm.ActionEdited + case "pull_request_review_rejected": + return scm.ActionDismissed + default: + return } } @@ -333,14 +372,20 @@ func convertAction(src string) (action scm.Action) { return scm.ActionReopen case "close", "closed": return scm.ActionClose - case "label", "labeled": + case "label", "labeled", "label_updated": return scm.ActionLabel - case "unlabel", "unlabeled": + case "unlabel", "unlabeled", "label_cleared": return scm.ActionUnlabel case "merge", "merged": return scm.ActionMerge case "synchronize", "synchronized": return scm.ActionSync + case "assigned": + return scm.ActionAssigned + case "unassigned": + return scm.ActionUnassigned + case "reviewed": + return scm.ActionSubmitted default: return } diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/deploy.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/deploy.go index 810509011..69873a0db 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/deploy.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/deploy.go @@ -3,10 +3,13 @@ package github import ( "context" "fmt" + "io/ioutil" "strconv" "strings" "time" + "github.com/pkg/errors" + "github.com/jenkins-x/go-scm/scm" ) @@ -18,29 +21,32 @@ type deployment struct { Namespace string Name string FullName string - ID int `json:"id"` - Link string `json:"url"` - Sha string `json:"sha"` - Ref string `json:"ref"` - Description string `json:"description"` - OriginalEnvironment string `json:"original_environment"` - Environment string `json:"environment"` - RepositoryLink string `json:"repository_url"` - StatusLink string `json:"statuses_url"` - Author *user `json:"creator"` - Created time.Time `json:"created_at"` - Updated time.Time `json:"updated_at"` - TransientEnvironment bool `json:"transient_environment"` - ProductionEnvironment bool `json:"production_environment"` + ID int `json:"id"` + Link string `json:"url"` + Sha string `json:"sha"` + Ref string `json:"ref"` + Task string `json:"task"` + Description string `json:"description"` + OriginalEnvironment string `json:"original_environment"` + Environment string `json:"environment"` + EnvironmentURL string `json:"environment_url"` + RepositoryLink string `json:"repository_url"` + StatusLink string `json:"statuses_url"` + Author *user `json:"creator"` + Created time.Time `json:"created_at"` + Updated time.Time `json:"updated_at"` + TransientEnvironment bool `json:"transient_environment"` + ProductionEnvironment bool `json:"production_environment"` + Payload interface{} `json:"payload"` } type deploymentInput struct { - Ref string `json:"ref"` - Task string `json:"task"` - Payload string `json:"payload"` - Environment string `json:"environment"` - Description string `json:"description"` - RequiredContexts []string `json:"required_contexts"` + Ref string `json:"ref,omitempty"` + Task string `json:"task,omitempty"` + Payload string `json:"payload,omitempty"` + Environment string `json:"environment,omitempty"` + Description string `json:"description,omitempty"` + RequiredContexts []string `json:"required_contexts,omitempty"` AutoMerge bool `json:"auto_merge"` TransientEnvironment bool `json:"transient_environment"` ProductionEnvironment bool `json:"production_environment"` @@ -75,14 +81,14 @@ func (s *deploymentService) Find(ctx context.Context, repoFullName string, deplo path := fmt.Sprintf("repos/%s/deployments/%s", repoFullName, deploymentID) out := new(deployment) res, err := s.client.do(ctx, "GET", path, nil, out) - return convertDeployment(out, repoFullName), res, err + return convertDeployment(out, repoFullName), res, wrapError(res, err) } func (s *deploymentService) List(ctx context.Context, repoFullName string, opts scm.ListOptions) ([]*scm.Deployment, *scm.Response, error) { path := fmt.Sprintf("repos/%s/deployments?%s", repoFullName, encodeListOptions(opts)) out := []*deployment{} res, err := s.client.do(ctx, "GET", path, nil, &out) - return convertDeploymentList(out, repoFullName), res, err + return convertDeploymentList(out, repoFullName), res, wrapError(res, err) } func (s *deploymentService) Create(ctx context.Context, repoFullName string, deploymentInput *scm.DeploymentInput) (*scm.Deployment, *scm.Response, error) { @@ -90,7 +96,7 @@ func (s *deploymentService) Create(ctx context.Context, repoFullName string, dep in := convertToDeploymentInput(deploymentInput) out := new(deployment) res, err := s.client.do(ctx, "POST", path, in, out) - return convertDeployment(out, repoFullName), res, err + return convertDeployment(out, repoFullName), res, wrapError(res, err) } func (s *deploymentService) Delete(ctx context.Context, repoFullName string, deploymentID string) (*scm.Response, error) { @@ -102,14 +108,14 @@ func (s *deploymentService) FindStatus(ctx context.Context, repoFullName string, path := fmt.Sprintf("repos/%s/deployments/%s/statuses/%s", repoFullName, deploymentID, statusID) out := new(deploymentStatus) res, err := s.client.do(ctx, "GET", path, nil, out) - return convertDeploymentStatus(out), res, err + return convertDeploymentStatus(out), res, wrapError(res, err) } func (s *deploymentService) ListStatus(ctx context.Context, repoFullName string, deploymentID string, opts scm.ListOptions) ([]*scm.DeploymentStatus, *scm.Response, error) { path := fmt.Sprintf("repos/%s/deployments/%s/statuses?%s", repoFullName, deploymentID, encodeListOptions(opts)) out := []*deploymentStatus{} res, err := s.client.do(ctx, "GET", path, nil, &out) - return convertDeploymentStatusList(out), res, err + return convertDeploymentStatusList(out), res, wrapError(res, err) } func (s *deploymentService) CreateStatus(ctx context.Context, repoFullName string, deploymentID string, deploymentStatusInput *scm.DeploymentStatusInput) (*scm.DeploymentStatus, *scm.Response, error) { @@ -117,7 +123,18 @@ func (s *deploymentService) CreateStatus(ctx context.Context, repoFullName strin in := convertToDeploymentStatusInput(deploymentStatusInput) out := new(deploymentStatus) res, err := s.client.do(ctx, "POST", path, in, out) - return convertDeploymentStatus(out), res, err + return convertDeploymentStatus(out), res, wrapError(res, err) +} + +func wrapError(res *scm.Response, err error) error { + if res == nil { + return err + } + data, err2 := ioutil.ReadAll(res.Body) + if err2 != nil { + return errors.Wrapf(err, "http status %d", res.Status) + } + return errors.Wrapf(err, "http status %d mesage %s", res.Status, string(data)) } func convertDeploymentList(out []*deployment, fullName string) []*scm.Deployment { @@ -158,6 +175,7 @@ func convertDeployment(from *deployment, fullName string) *scm.Deployment { Sha: from.Sha, Ref: from.Ref, FullName: fullName, + Task: from.Task, Description: from.Description, OriginalEnvironment: from.OriginalEnvironment, Environment: from.Environment, @@ -168,6 +186,7 @@ func convertDeployment(from *deployment, fullName string) *scm.Deployment { Updated: from.Updated, TransientEnvironment: from.TransientEnvironment, ProductionEnvironment: from.ProductionEnvironment, + Payload: from.Payload, } names := strings.Split(fullName, "/") if len(names) > 1 { diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/git.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/git.go index 95ad49d6f..44a79eff5 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/git.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/git.go @@ -108,6 +108,13 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.Li return convertChangeList(out.Files), res, err } +func (s *gitService) CompareCommits(ctx context.Context, repo, ref1, ref2 string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + path := fmt.Sprintf("/repos/%s/compare/%s...%s", repo, ref1, ref2) + out := new(commit) + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertChangeList(out.Files), res, err +} + type branch struct { Name string `json:"name"` Commit commit `json:"commit"` diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/github.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/github.go index f0d9b7600..f0f23b94f 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/github.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/github.go @@ -9,6 +9,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "net/http" "net/url" @@ -25,6 +26,7 @@ import ( // but will prevent an indefinite stall if GitHub never responds. const maxRequestTime = 5 * time.Minute +// NewWebHookService creates a new instance of the webhook service without the rest of the client func NewWebHookService() scm.WebhookService { return &webhookService{nil} } @@ -46,6 +48,8 @@ func New(uri string) (*scm.Client, error) { client.Deployments = &deploymentService{client} client.Git = &gitService{client} client.Issues = &issueService{client} + client.Milestones = &milestoneService{client} + client.Releases = &releaseService{client} client.Organizations = &organizationService{client} client.PullRequests = &pullService{&issueService{client}} client.Repositories = &repositoryService{client} @@ -54,9 +58,9 @@ func New(uri string) (*scm.Client, error) { client.Webhooks = &webhookService{client} client.Apps = &appService{client} - graphqlEndpoint := scm.UrlJoin(uri, "/graphql") + graphqlEndpoint := scm.URLJoin(uri, "/graphql") if strings.HasSuffix(uri, "/api/v3") { - graphqlEndpoint = scm.UrlJoin(uri[0:len(uri)-2], "graphql") + graphqlEndpoint = scm.URLJoin(uri[0:len(uri)-2], "graphql") } client.GraphQLURL, err = url.Parse(graphqlEndpoint) if err != nil { @@ -157,9 +161,9 @@ func (c *wrapper) doRequest(ctx context.Context, req *scm.Request, in, out inter if res.Status == 404 { return res, scm.ErrNotFound } - err := new(Error) - json.NewDecoder(res.Body).Decode(err) - return res, err + return res, errors.New( + http.StatusText(res.Status), + ) } if out == nil { diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/issue.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/issue.go index 3c5f35110..37321f0bd 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/issue.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/issue.go @@ -222,6 +222,26 @@ func (s *issueService) Unlock(ctx context.Context, repo string, number int) (*sc return res, err } +func (s *issueService) SetMilestone(ctx context.Context, repo string, issueID int, number int) (*scm.Response, error) { + path := fmt.Sprintf("repos/%s/issues/%d", repo, issueID) + in := &struct { + Milestone int `json:"milestone"` + }{ + Milestone: number, + } + res, err := s.client.do(ctx, "PATCH", path, in, nil) + return res, err +} + +func (s *issueService) ClearMilestone(ctx context.Context, repo string, id int) (*scm.Response, error) { + path := fmt.Sprintf("repos/%s/issues/%d", repo, id) + in := &struct { + Milestone interface{} `json:"milestone"` + }{} + res, err := s.client.do(ctx, "PATCH", path, in, nil) + return res, err +} + type issue struct { ID int `json:"id"` HTMLURL string `json:"html_url"` @@ -233,6 +253,10 @@ type issue struct { Login string `json:"login"` AvatarURL string `json:"avatar_url"` } `json:"user"` + ClosedBy *struct { + Login string `json:"login"` + AvatarURL string `json:"avatar_url"` + } `json:"closed_by"` Labels []struct { Name string `json:"name"` } `json:"labels"` @@ -318,6 +342,13 @@ func populateRepositoryFromURL(repo *scm.Repository, u string) { // helper function to convert from the gogs issue structure to // the common issue structure. func convertIssue(from *issue) *scm.Issue { + var closedBy *scm.User + if from.ClosedBy != nil { + closedBy = &scm.User{ + Login: from.ClosedBy.Login, + Avatar: from.ClosedBy.AvatarURL, + } + } return &scm.Issue{ Number: from.Number, Title: from.Title, @@ -331,6 +362,7 @@ func convertIssue(from *issue) *scm.Issue { Login: from.User.Login, Avatar: from.User.AvatarURL, }, + ClosedBy: closedBy, Assignees: convertUsers(from.Assignees), PullRequest: from.PullRequest != nil, Created: from.CreatedAt, diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/milestone.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/milestone.go new file mode 100644 index 000000000..fc3f9dcc6 --- /dev/null +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/milestone.go @@ -0,0 +1,111 @@ +package github + +import ( + "context" + "fmt" + "time" + + "github.com/jenkins-x/go-scm/scm" +) + +type milestoneService struct { + client *wrapper +} + +type milestone struct { + ID int `json:"id"` + Number int `json:"number"` + Title string `json:"title"` + Description string `json:"description"` + State string `json:"state"` + DueOn time.Time `json:"due_on"` + URL string `json:"url"` + HTMLURL string `json:"html_url"` + LabelsURL string `json:"labels_url"` + Creator user `json:"creator"` + OpenIssues int `json:"open_issues"` + ClosedIssues int `json:"closed_issues"` + NodeID string `json:"node_id"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + ClosedAt time.Time `json:"closed_at"` +} + +type milestoneInput struct { + Title string `json:"title"` + State string `json:"state"` + Description string `json:"description"` + DueOn time.Time `json:"due_on"` +} + +func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/milestones/%d", repo, id) + out := new(milestone) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertMilestone(out), res, err +} + +func (s *milestoneService) List(ctx context.Context, repo string, opts scm.MilestoneListOptions) ([]*scm.Milestone, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/milestones?%s", repo, encodeMilestoneListOptions(opts)) + out := []*milestone{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertMilestoneList(out), res, err +} + +func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/milestones", repo) + in := &milestoneInput{ + Title: input.Title, + State: input.State, + Description: input.Description, + DueOn: *input.DueDate, + } + out := new(milestone) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertMilestone(out), res, err +} + +func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + path := fmt.Sprintf("repos/%s/milestones/%d", repo, id) + return s.client.do(ctx, "DELETE", path, nil, nil) +} + +func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/milestones/%d", repo, id) + in := &milestoneInput{} + if input.Title != "" { + in.Title = input.Title + } + if input.State != "" { + in.State = input.State + } + if input.Description != "" { + in.Description = input.Description + } + if input.DueDate != nil { + in.DueOn = *input.DueDate + } + out := new(milestone) + res, err := s.client.do(ctx, "PATCH", path, in, out) + return convertMilestone(out), res, err +} + +func convertMilestoneList(from []*milestone) []*scm.Milestone { + var to []*scm.Milestone + for _, m := range from { + to = append(to, convertMilestone(m)) + } + return to +} + +func convertMilestone(from *milestone) *scm.Milestone { + return &scm.Milestone{ + Number: from.Number, + ID: from.ID, + Title: from.Title, + Description: from.Description, + Link: from.HTMLURL, + State: from.State, + DueDate: &from.DueOn, + } +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/org.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/org.go index fa79c3508..a0429fc0f 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/org.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/org.go @@ -40,12 +40,35 @@ type team struct { ParentTeamID *int `json:"parent_team_id,omitempty"` // Only valid in creates/edits } +type pendingInvitations struct { + ID int `json:"id"` + Login string `json:"login"` + Role string `json:"role"` + Inviter inviter `json:"inviter"` +} + +type inviter struct { + ID int `json:"id"` + Login string `json:"login"` +} + type teamMember struct { Login string `json:"login"` } type membership struct { - Role string `json:"role"` + Role string `json:"role"` + State string `json:"state"` + User user `json:"user"` + Organization organization `json:"organization"` +} + +func (s *organizationService) Create(context.Context, *scm.OrganizationInput) (*scm.Organization, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *organizationService) Delete(context.Context, string) (*scm.Response, error) { + return nil, scm.ErrNotSupported } func (s *organizationService) IsMember(ctx context.Context, org string, user string) (bool, *scm.Response, error) { @@ -143,6 +166,64 @@ func (s *organizationService) ListTeamMembers(ctx context.Context, id int, role return convertTeamMembers(out), res, err } +// ListPendingInvitations lists the pending invitations for an organisation +// see https://developer.github.com/v3/orgs/members/#list-pending-organization-invitations +func (s *organizationService) ListPendingInvitations(ctx context.Context, org string, opts scm.ListOptions) ([]*scm.OrganizationPendingInvite, *scm.Response, error) { + req := &scm.Request{ + Method: http.MethodGet, + Path: fmt.Sprintf("orgs/%s/invitations?%s", org, encodeListOptions(opts)), + } + out := []*pendingInvitations{} + res, err := s.client.doRequest(ctx, req, nil, &out) + return convertOrganisationPendingInvites(out), res, err +} + +// ListMemberships lists organisation memberships for the authenticated user +// see https://developer.github.com/v3/orgs/members/#list-organization-memberships-for-the-authenticated-user +func (s *organizationService) ListMemberships(ctx context.Context, opts scm.ListOptions) ([]*scm.Membership, *scm.Response, error) { + req := &scm.Request{ + Method: http.MethodGet, + Path: fmt.Sprintf("/user/memberships/orgs?%s", encodeListOptions(opts)), + } + out := []*membership{} + res, err := s.client.doRequest(ctx, req, nil, &out) + return convertMemberships(out), res, err +} + +// AcceptOrganizationInvitation accepts an invitation for an organisation +func (s *organizationService) AcceptOrganizationInvitation(ctx context.Context, org string) (*scm.Response, error) { + req := &scm.Request{ + Method: http.MethodPatch, + Path: fmt.Sprintf("/user/memberships/orgs/%s", org), + } + values := map[string]string{"state": "active"} + return s.client.doRequest(ctx, req, values, nil) +} + +func convertOrganisationPendingInvites(from []*pendingInvitations) []*scm.OrganizationPendingInvite { + to := []*scm.OrganizationPendingInvite{} + for _, v := range from { + to = append(to, &scm.OrganizationPendingInvite{ + ID: v.ID, + Login: v.Login, + InviterLogin: v.Inviter.Login, + }) + } + return to +} + +func convertMemberships(from []*membership) []*scm.Membership { + to := []*scm.Membership{} + for _, v := range from { + to = append(to, &scm.Membership{ + OrganizationName: v.Organization.Login, + State: v.State, + Role: v.Role, + }) + } + return to +} + func convertOrganizationList(from []*organization) []*scm.Organization { to := []*scm.Organization{} for _, v := range from { diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/pr.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/pr.go index 4f0b05b09..30ab298d3 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/pr.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/pr.go @@ -205,14 +205,6 @@ type prBranch struct { User user `json:"user"` Repo repository `json:"repo"` } -type milestone struct { - Number int `json:"number"` - ID int `json:"id"` - Title string `json:"title"` - Description string `json:"Description"` - Link string `json:"html_url"` - State string `json:"state"` -} type pr struct { Number int `json:"number"` diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/release.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/release.go new file mode 100644 index 000000000..2b85904b7 --- /dev/null +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/release.go @@ -0,0 +1,126 @@ +package github + +import ( + "context" + "fmt" + + "github.com/jenkins-x/go-scm/scm" +) + +type releaseService struct { + client *wrapper +} + +type release struct { + ID int `json:"id"` + Title string `json:"name"` + Description string `json:"body"` + Link string `json:"html_url,omitempty"` + Tag string `json:"tag_name,omitempty"` + Commitish string `json:"target_commitish,omitempty"` + Draft bool `json:"draft"` + Prerelease bool `json:"prerelease"` +} + +type releaseInput struct { + Title string `json:"name"` + Description string `json:"body"` + Tag string `json:"tag_name"` + Commitish string `json:"target_commitish"` + Draft bool `json:"draft"` + Prerelease bool `json:"prerelease"` +} + +func (s *releaseService) Find(ctx context.Context, repo string, id int) (*scm.Release, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/releases/%d", repo, id) + out := new(release) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertRelease(out), res, err +} + +func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/releases/tags/%s", repo, tag) + out := new(release) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertRelease(out), res, err +} + +func (s *releaseService) List(ctx context.Context, repo string, opts scm.ReleaseListOptions) ([]*scm.Release, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/releases?%s", repo, encodeReleaseListOptions(opts)) + out := []*release{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertReleaseList(out), res, err +} + +func (s *releaseService) Create(ctx context.Context, repo string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/releases", repo) + in := &releaseInput{ + Title: input.Title, + Commitish: input.Commitish, + Description: input.Description, + Draft: input.Draft, + Prerelease: input.Prerelease, + Tag: input.Tag, + } + out := new(release) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertRelease(out), res, err +} + +func (s *releaseService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + path := fmt.Sprintf("repos/%s/releases/%d", repo, id) + return s.client.do(ctx, "DELETE", path, nil, nil) +} + +func (s *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) { + rel, _, _ := s.FindByTag(ctx, repo, tag) + return s.Delete(ctx, repo, rel.ID) +} + +func (s *releaseService) Update(ctx context.Context, repo string, id int, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/releases/%d", repo, id) + in := &releaseInput{} + if input.Title != "" { + in.Title = input.Title + } + if input.Description != "" { + in.Description = input.Description + } + if input.Commitish != "" { + in.Commitish = input.Commitish + } + if input.Tag != "" { + in.Tag = input.Tag + } + in.Draft = input.Draft + in.Prerelease = input.Prerelease + out := new(release) + res, err := s.client.do(ctx, "PATCH", path, in, out) + return convertRelease(out), res, err +} + +func (s *releaseService) UpdateByTag(ctx context.Context, repo string, tag string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + rel, _, _ := s.FindByTag(ctx, repo, tag) + return s.Update(ctx, repo, rel.ID, input) +} + +func convertReleaseList(from []*release) []*scm.Release { + var to []*scm.Release + for _, m := range from { + to = append(to, convertRelease(m)) + } + return to +} + +func convertRelease(from *release) *scm.Release { + return &scm.Release{ + ID: from.ID, + Title: from.Title, + Description: from.Description, + Link: from.Link, + Tag: from.Tag, + Commitish: from.Commitish, + Draft: from.Draft, + Prerelease: from.Prerelease, + } +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/repo.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/repo.go index 61f7fe505..d3b7f2773 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/repo.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/repo.go @@ -54,6 +54,7 @@ type hook struct { URL string `json:"url"` Secret string `json:"secret"` ContentType string `json:"content_type"` + InsecureSSL string `json:"insecure_ssl"` } `json:"config"` } @@ -293,6 +294,11 @@ func (s *repositoryService) CreateHook(ctx context.Context, repo string, input * in.Config.Secret = input.Secret in.Config.ContentType = "json" in.Config.URL = input.Target + if input.SkipVerify { + in.Config.InsecureSSL = "1" + } else { + in.Config.InsecureSSL = "0" + } in.Events = append( input.NativeEvents, convertHookEvents(input.Events)..., @@ -322,12 +328,19 @@ func (s *repositoryService) DeleteHook(ctx context.Context, repo string, id stri return s.client.do(ctx, "DELETE", path, nil, nil) } +func (s *repositoryService) Delete(ctx context.Context, repo string) (*scm.Response, error) { + path := fmt.Sprintf("repos/%s", repo) + return s.client.do(ctx, "DELETE", path, nil, nil) +} + // helper function to convert from the gogs repository list to // the common repository structure. func convertRepositoryList(from []*repository) []*scm.Repository { to := []*scm.Repository{} for _, v := range from { - to = append(to, convertRepository(v)) + if v != nil { + to = append(to, convertRepository(v)) + } } return to } @@ -364,11 +377,18 @@ func convertHookList(from []*hook) []*scm.Hook { } func convertHook(from *hook) *scm.Hook { + + skipVerify := false + if from.Config.InsecureSSL == "1" { + skipVerify = true + } + return &scm.Hook{ - ID: strconv.Itoa(from.ID), - Active: from.Active, - Target: from.Config.URL, - Events: from.Events, + ID: strconv.Itoa(from.ID), + Active: from.Active, + Target: from.Config.URL, + SkipVerify: skipVerify, + Events: from.Events, } } @@ -380,6 +400,9 @@ func convertHookEvents(from scm.HookEvents) []string { if from.PullRequest { events = append(events, "pull_request") } + if from.Review { + events = append(events, "pull_request_review") + } if from.PullRequestComment { events = append(events, "pull_request_review_comment") } diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/user.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/user.go index 2cc60324a..a3c638d12 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/user.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/user.go @@ -17,6 +17,14 @@ type userService struct { client *wrapper } +func (s *userService) CreateToken(context.Context, string, string) (*scm.UserToken, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *userService) DeleteToken(context.Context, int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + func (s *userService) Find(ctx context.Context) (*scm.User, *scm.Response, error) { out := new(user) res, err := s.client.do(ctx, "GET", "user", nil, out) diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/util.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/util.go index facb09cb5..5216147a0 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/util.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/util.go @@ -92,6 +92,22 @@ func encodePullRequestListOptions(opts scm.PullRequestListOptions) string { return params.Encode() } +func encodeMilestoneListOptions(opts scm.MilestoneListOptions) string { + params := url.Values{} + if opts.Page != 0 { + params.Set("page", strconv.Itoa(opts.Page)) + } + if opts.Size != 0 { + params.Set("per_page", strconv.Itoa(opts.Size)) + } + if opts.Open && opts.Closed { + params.Set("state", "all") + } else if opts.Closed { + params.Set("state", "closed") + } + return params.Encode() +} + func encodePullRequestMergeOptions(opts *scm.PullRequestMergeOptions) *pullRequestMergeRequest { mr := &pullRequestMergeRequest{} if opts.MergeMethod != "" { @@ -105,3 +121,19 @@ func encodePullRequestMergeOptions(opts *scm.PullRequestMergeOptions) *pullReque } return mr } + +func encodeReleaseListOptions(opts scm.ReleaseListOptions) string { + params := url.Values{} + if opts.Page != 0 { + params.Set("page", strconv.Itoa(opts.Page)) + } + if opts.Size != 0 { + params.Set("per_page", strconv.Itoa(opts.Size)) + } + if opts.Open && opts.Closed { + params.Set("state", "all") + } else if opts.Closed { + params.Set("state", "closed") + } + return params.Encode() +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/webhook.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/webhook.go index 1071fffd1..0f80a12ee 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/github/webhook.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/github/webhook.go @@ -16,7 +16,6 @@ import ( "github.com/jenkins-x/go-scm/pkg/hmac" "github.com/jenkins-x/go-scm/scm" - "github.com/jenkins-x/go-scm/scm/driver/internal/null" "github.com/sirupsen/logrus" ) @@ -45,7 +44,7 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo guid := req.Header.Get("X-GitHub-Delivery") if guid == "" { - return nil, scm.MissingHeader{"X-GitHub-Delivery"} + return nil, scm.MissingHeader{Header: "X-GitHub-Delivery"} } var hook scm.Webhook @@ -95,7 +94,7 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo hook, err = s.parseWatchHook(data) default: log.WithField("Event", event).Warnf("unknown webhook") - return nil, scm.UnknownWebhook{event} + return nil, scm.UnknownWebhook{Event: event} } if err != nil { return nil, err @@ -330,6 +329,8 @@ func (s *webhookService) parsePullRequestHook(data []byte, guid string) (scm.Web dst.Action = scm.ActionSync case "ready_for_review": dst.Action = scm.ActionReadyForReview + case "converted_to_draft": + dst.Action = scm.ActionConvertedToDraft } return dst, nil } @@ -439,8 +440,9 @@ type ( Installation *installationRef `json:"installation"` } - // github deployment_status payload - deploymentStatusHook struct { + // github deployment webhook payload + deploymentHook struct { + Deployment deployment `json:"deployment"` Action string `json:"action"` Repository repository `json:"repository"` Sender user `json:"sender"` @@ -448,6 +450,17 @@ type ( Installation *installationRef `json:"installation"` } + // github deployment_status payload + deploymentStatusHook struct { + DeploymentStatus deploymentStatus `json:"deployment_status"` + Deployment deployment `json:"deployment"` + Action string `json:"action"` + Repository repository `json:"repository"` + Sender user `json:"sender"` + Label label `json:"label"` + Installation *installationRef `json:"installation"` + } + // github deployment_status payload forkHook struct { Repository repository `json:"repository"` @@ -652,23 +665,6 @@ type ( Position *int `json:"position"` } - // github deployment webhook payload - deploymentHook struct { - Deployment struct { - Creator user `json:"creator"` - Description null.String `json:"description"` - Environment null.String `json:"environment"` - EnvironmentURL null.String `json:"environment_url"` - Sha null.String `json:"sha"` - Ref null.String `json:"ref"` - Task null.String `json:"task"` - Payload interface{} `json:"payload"` - } `json:"deployment"` - Repository repository `json:"repository"` - Sender user `json:"sender"` - Installation *installationRef `json:"installation"` - } - // installationHook a webhook invoked when the GitHub App is installed installationHook struct { Action string `json:"action"` @@ -844,13 +840,37 @@ func convertCheckSuiteHook(dst *checkSuiteHook) *scm.CheckSuiteHook { } } +func convertDeploymentHook(src *deploymentHook) *scm.DeployHook { + dst := &scm.DeployHook{ + Deployment: *convertDeployment(&src.Deployment, src.Repository.FullName), + Ref: scm.Reference{ + Name: src.Deployment.Ref, + Path: src.Deployment.Ref, + Sha: src.Deployment.Sha, + }, + Action: convertAction(src.Action), + Repo: *convertRepository(&src.Repository), + Sender: *convertUser(&src.Sender), + Label: convertLabel(src.Label), + Installation: convertInstallationRef(src.Installation), + } + if tagRE.MatchString(dst.Ref.Name) { + dst.Ref.Path = scm.ExpandRef(dst.Ref.Path, "refs/tags/") + } else { + dst.Ref.Path = scm.ExpandRef(dst.Ref.Path, "refs/heads/") + } + return dst +} + func convertDeploymentStatusHook(dst *deploymentStatusHook) *scm.DeploymentStatusHook { return &scm.DeploymentStatusHook{ - Action: convertAction(dst.Action), - Repo: *convertRepository(&dst.Repository), - Sender: *convertUser(&dst.Sender), - Label: convertLabel(dst.Label), - Installation: convertInstallationRef(dst.Installation), + Deployment: *convertDeployment(&dst.Deployment, dst.Repository.FullName), + DeploymentStatus: *convertDeploymentStatus(&dst.DeploymentStatus), + Action: convertAction(dst.Action), + Repo: *convertRepository(&dst.Repository), + Sender: *convertUser(&dst.Sender), + Label: convertLabel(dst.Label), + Installation: convertInstallationRef(dst.Installation), } } @@ -1113,40 +1133,6 @@ func convertPullRequestComment(comment *reviewCommentFromHook) *scm.Comment { } } -func convertDeploymentHook(src *deploymentHook) *scm.DeployHook { - dst := &scm.DeployHook{ - Data: src.Deployment.Payload, - Desc: src.Deployment.Description.String, - Ref: scm.Reference{ - Name: src.Deployment.Ref.String, - Path: src.Deployment.Ref.String, - Sha: src.Deployment.Sha.String, - }, - Repo: scm.Repository{ - ID: fmt.Sprint(src.Repository.ID), - Namespace: src.Repository.Owner.Login, - Name: src.Repository.Name, - FullName: src.Repository.FullName, - Branch: src.Repository.DefaultBranch, - Private: src.Repository.Private, - Clone: src.Repository.CloneURL, - CloneSSH: src.Repository.SSHURL, - Link: src.Repository.HTMLURL, - }, - Sender: *convertUser(&src.Sender), - Task: src.Deployment.Task.String, - Target: src.Deployment.Environment.String, - TargetURL: src.Deployment.EnvironmentURL.String, - Installation: convertInstallationRef(src.Installation), - } - if tagRE.MatchString(dst.Ref.Name) { - dst.Ref.Path = scm.ExpandRef(dst.Ref.Path, "refs/tags/") - } else { - dst.Ref.Path = scm.ExpandRef(dst.Ref.Path, "refs/heads/") - } - return dst -} - // regexp help determine if the named git object is a tag. // this is not meant to be 100% accurate. var tagRE = regexp.MustCompile("^v?(\\d+).(.+)") diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/content.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/content.go index b0e3fc261..b419ce042 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/content.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/content.go @@ -40,7 +40,10 @@ func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm } func (s *contentService) List(ctx context.Context, repo, path, ref string) ([]*scm.FileEntry, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + endpoint := fmt.Sprintf("api/v4/projects/%s/repository/tree?path=%s&ref=%s", encode(repo), path, ref) + out := []*entry{} + res, err := s.client.do(ctx, "GET", endpoint, nil, &out) + return convertEntryList(out), res, err } func (s *contentService) Create(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { @@ -105,3 +108,31 @@ type updateContentBody struct { Content string `json:"content"` Message string `json:"commit_message"` } + +type entry struct { + ID string `json:"id"` + Name string `json:"name"` + Type string `json:"type"` + Path string `json:"path"` + Mode string `json:"mode"` +} + +func convertEntryList(out []*entry) []*scm.FileEntry { + answer := make([]*scm.FileEntry, 0, len(out)) + for _, o := range out { + answer = append(answer, convertEntry(o)) + } + return answer +} + +func convertEntry(from *entry) *scm.FileEntry { + t := "file" + if from.Type == "tree" { + t = "dir" + } + return &scm.FileEntry{ + Name: from.Name, + Path: from.Path, + Type: t, + } +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/git.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/git.go index 40ffc2c44..c5b5219a1 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/git.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/git.go @@ -51,14 +51,14 @@ func (s *gitService) CreateRef(ctx context.Context, repo, ref, sha string) (*scm out := &struct { Name string `json:"name"` Commit struct { - Id string `json:"id"` + ID string `json:"id"` } `json:"commit"` }{} res, err := s.client.do(ctx, "POST", path, nil, out) scmRef := &scm.Reference{ Name: out.Name, - Sha: out.Commit.Id, + Sha: out.Commit.ID, } return scmRef, res, err } @@ -68,21 +68,21 @@ func (s *gitService) DeleteRef(ctx context.Context, repo, ref string) (*scm.Resp } func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { - path := fmt.Sprintf("api/v4/projects/%s/repository/branches/%s", encode(repo), name) + path := fmt.Sprintf("api/v4/projects/%s/repository/branches/%s", encode(repo), encode(name)) out := new(branch) res, err := s.client.do(ctx, "GET", path, nil, out) return convertBranch(out), res, err } func (s *gitService) FindCommit(ctx context.Context, repo, ref string) (*scm.Commit, *scm.Response, error) { - path := fmt.Sprintf("api/v4/projects/%s/repository/commits/%s", encode(repo), ref) + path := fmt.Sprintf("api/v4/projects/%s/repository/commits/%s", encode(repo), encode(scm.TrimRef(ref))) out := new(commit) res, err := s.client.do(ctx, "GET", path, nil, out) return convertCommit(out), res, err } func (s *gitService) FindTag(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { - path := fmt.Sprintf("api/v4/projects/%s/repository/tags/%s", encode(repo), name) + path := fmt.Sprintf("api/v4/projects/%s/repository/tags/%s", encode(repo), encode(name)) out := new(branch) res, err := s.client.do(ctx, "GET", path, nil, out) return convertTag(out), res, err @@ -110,12 +110,25 @@ func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOpt } func (s *gitService) ListChanges(ctx context.Context, repo, ref string, opts scm.ListOptions) ([]*scm.Change, *scm.Response, error) { - path := fmt.Sprintf("api/v4/projects/%s/repository/commits/%s/diff", encode(repo), ref) + path := fmt.Sprintf("api/v4/projects/%s/repository/commits/%s/diff", encode(repo), encode(ref)) out := []*change{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertChangeList(out), res, err } +func (s *gitService) CompareCommits(ctx context.Context, repo, ref1, ref2 string, opts scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + opts.From = encode(ref1) + opts.To = encode(ref2) + path := fmt.Sprintf("api/v4/projects/%s/repository/compare?%s", encode(repo), encodeListOptions(opts)) + out := compare{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertChangeList(out.Diffs), res, err +} + +type compare struct { + Diffs []*change `json:"diffs"` +} + type branch struct { Name string `json:"name"` Commit struct { @@ -134,6 +147,7 @@ type commit struct { CommitterName string `json:"committer_name"` CommitterEmail string `json:"committer_email"` Created time.Time `json:"created_at"` + URL string `json:"web_url"` } func convertCommitList(from []*commit) []*scm.Commit { @@ -148,6 +162,7 @@ func convertCommit(from *commit) *scm.Commit { return &scm.Commit{ Message: from.Message, Sha: from.ID, + Link: from.URL, Author: scm.Signature{ Login: from.AuthorName, Name: from.AuthorName, diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/gitlab.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/gitlab.go index 605b23de0..59825e6ad 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/gitlab.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/gitlab.go @@ -9,6 +9,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "net/http" "net/url" @@ -20,8 +21,9 @@ import ( "github.com/shurcooL/graphql" ) +// NewWebHookService creates a new instance of the webhook service without the rest of the client func NewWebHookService() scm.WebhookService { - return &webhookService{nil} + return &webhookService{nil, nil} } // New returns a new GitLab API client. @@ -40,14 +42,22 @@ func New(uri string) (*scm.Client, error) { client.Contents = &contentService{client} client.Git = &gitService{client} client.Issues = &issueService{client} + client.Releases = &releaseService{client} + client.Milestones = &milestoneService{client} client.Organizations = &organizationService{client} client.PullRequests = &pullService{client} client.Repositories = &repositoryService{client} client.Reviews = &reviewService{client} - client.Users = &userService{client} - client.Webhooks = &webhookService{client} - graphqlEndpoint := scm.UrlJoin(uri, "/api/graphql") + //add the user service to the webhook service so it can be used for fetching users + us := &userService{client} + client.Users = us + client.Webhooks = &webhookService{ + client: client, + userService: us, + } + + graphqlEndpoint := scm.URLJoin(uri, "/api/graphql") client.GraphQLURL, err = url.Parse(graphqlEndpoint) if err != nil { return nil, err @@ -92,7 +102,7 @@ type wrapper struct { *scm.Client } -type gl_namespace struct { +type gitlabNamespace struct { ID int `json:"id"` Name string `json:"name"` Path string `json:"path"` @@ -103,15 +113,17 @@ type gl_namespace struct { } // findNamespaceByName will look up the namespace for the given name -func (c *wrapper) findNamespaceByName(ctx context.Context, name string) (*gl_namespace, error) { +func (c *wrapper) findNamespaceByName(ctx context.Context, name string) (*gitlabNamespace, error) { in := url.Values{} in.Set("search", name) path := fmt.Sprintf("api/v4/namespaces?%s", in.Encode()) - out := new(gl_namespace) + var out []*gitlabNamespace _, err := c.do(ctx, "GET", path, nil, &out) - - return out, err + if len(out) > 0 { + return out[0], err + } + return nil, err } // do wraps the Client.Do function by creating the Request and @@ -159,9 +171,9 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface // if an error is encountered, unmarshal and return the // error response. if res.Status > 300 { - err := new(Error) - json.NewDecoder(res.Body).Decode(err) - return res, err + return res, errors.New( + http.StatusText(res.Status), + ) } if out == nil { diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/issue.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/issue.go index 0aa4e6171..7595e21ff 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/issue.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/issue.go @@ -228,6 +228,25 @@ func (s *issueService) Unlock(ctx context.Context, repo string, number int) (*sc return res, err } +func (s *issueService) SetMilestone(ctx context.Context, repo string, issueID int, number int) (*scm.Response, error) { + in := &updateIssueOptions{ + MilestoneID: &number, + } + path := fmt.Sprintf("api/v4/projects/%s/issues/%d", encode(repo), issueID) + + return s.client.do(ctx, "PUT", path, in, nil) +} + +func (s *issueService) ClearMilestone(ctx context.Context, repo string, id int) (*scm.Response, error) { + zeroVal := 0 + in := &updateIssueOptions{ + MilestoneID: &zeroVal, + } + path := fmt.Sprintf("api/v4/projects/%s/issues/%d", encode(repo), id) + + return s.client.do(ctx, "PUT", path, in, nil) +} + type updateIssueOptions struct { Title *string `json:"title,omitempty"` Description *string `json:"description,omitempty"` diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/milestone.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/milestone.go new file mode 100644 index 000000000..e6956e555 --- /dev/null +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/milestone.go @@ -0,0 +1,166 @@ +package gitlab + +import ( + "context" + "errors" + "fmt" + "net/url" + "time" + + "github.com/jenkins-x/go-scm/scm" +) + +type milestoneService struct { + client *wrapper +} + +// isoTime represents an ISO 8601 formatted date +type isoTime time.Time + +// ISO 8601 date format +const iso8601 = "2006-01-02" + +// MarshalJSON implements the json.Marshaler interface +func (t isoTime) MarshalJSON() ([]byte, error) { + if y := time.Time(t).Year(); y < 0 || y >= 10000 { + // ISO 8901 uses 4 digits for the years + return nil, errors.New("json: ISOTime year outside of range [0,9999]") + } + + b := make([]byte, 0, len(iso8601)+2) + b = append(b, '"') + b = time.Time(t).AppendFormat(b, iso8601) + b = append(b, '"') + + return b, nil +} + +// UnmarshalJSON implements the json.Unmarshaler interface +func (t *isoTime) UnmarshalJSON(data []byte) error { + // Ignore null, like in the main JSON package + if string(data) == "null" { + return nil + } + + isotime, err := time.Parse(`"`+iso8601+`"`, string(data)) + *t = isoTime(isotime) + + return err +} + +// EncodeValues implements the query.Encoder interface +func (t *isoTime) EncodeValues(key string, v *url.Values) error { + if t == nil || (time.Time(*t)).IsZero() { + return nil + } + v.Add(key, t.String()) + return nil +} + +// String implements the Stringer interface +func (t isoTime) String() string { + return time.Time(t).Format(iso8601) +} + +type milestone struct { + ID int `json:"id"` + IID int `json:"iid"` + ProjectID int `json:"project_id"` + Title string `json:"title"` + Description string `json:"description"` + State string `json:"state"` + DueDate isoTime `json:"due_date"` + StartDate isoTime `json:"start_date"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + Expired bool `json:"expired"` +} + +type milestoneInput struct { + Title *string `json:"title"` + StateEvent *string `json:"state_event,omitempty"` + Description *string `json:"description"` + DueDate *isoTime `json:"due_date"` +} + +func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/milestones/%d", encode(repo), id) + out := new(milestone) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertMilestone(out), res, err +} + +func (s *milestoneService) List(ctx context.Context, repo string, opts scm.MilestoneListOptions) ([]*scm.Milestone, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/milestones?%s", encode(repo), encodeMilestoneListOptions(opts)) + out := []*milestone{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertMilestoneList(out), res, err +} + +func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/milestones", encode(repo)) + dueDateIso := isoTime(*input.DueDate) + in := &milestoneInput{ + Title: &input.Title, + Description: &input.Description, + DueDate: &dueDateIso, + } + out := new(milestone) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertMilestone(out), res, err +} + +func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/milestones/%d", encode(repo), id) + res, err := s.client.do(ctx, "DELETE", path, nil, nil) + return res, err +} + +func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/milestones/%d", encode(repo), id) + in := &milestoneInput{} + if input.Title != "" { + in.Title = &input.Title + } + if input.State != "" { + if input.State == "open" { + activate := "activate" + in.StateEvent = &activate + } else { + in.StateEvent = &input.State + } + } + if input.Description != "" { + in.Description = &input.Description + } + if input.DueDate != nil { + dueDateIso := isoTime(*input.DueDate) + in.DueDate = &dueDateIso + } + out := new(milestone) + res, err := s.client.do(ctx, "PATCH", path, in, out) + return convertMilestone(out), res, err +} + +func convertMilestoneList(from []*milestone) []*scm.Milestone { + var to []*scm.Milestone + for _, m := range from { + to = append(to, convertMilestone(m)) + } + return to +} + +func convertMilestone(from *milestone) *scm.Milestone { + if from == nil || from.Title == "" { + return nil + } + dueDate := time.Time(from.DueDate) + return &scm.Milestone{ + Number: from.ID, + ID: from.ID, + Title: from.Title, + Description: from.Description, + State: from.State, + DueDate: &dueDate, + } +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/org.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/org.go index b86f0dd51..30c264c0a 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/org.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/org.go @@ -16,19 +16,36 @@ type organizationService struct { client *wrapper } +func (s *organizationService) Create(context.Context, *scm.OrganizationInput) (*scm.Organization, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *organizationService) Delete(context.Context, string) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + func (s *organizationService) IsMember(ctx context.Context, org string, user string) (bool, *scm.Response, error) { - users, res, err := s.ListMemberUsers(ctx, org) - if err != nil { - return false, res, err + var resp *scm.Response + var users []scm.User + var err error + firstRun := false + opts := scm.ListOptions{ + Page: 1, } - member := false - for _, u := range users { - if u.Login == user { - member = true - break + for !firstRun || (resp != nil && opts.Page <= resp.Page.Last) { + users, resp, err = s.ListMemberUsers(ctx, org, opts) + if err != nil { + return false, resp, err + } + firstRun = true + for _, u := range users { + if u.Login == user { + return true, resp, nil + } } + opts.Page++ } - return member, res, err + return false, resp, err } func (s *organizationService) IsAdmin(ctx context.Context, org string, user string) (bool, *scm.Response, error) { @@ -47,7 +64,7 @@ func (s *organizationService) ListTeamMembers(ctx context.Context, id int, role } func (s *organizationService) ListOrgMembers(ctx context.Context, org string, ops scm.ListOptions) ([]*scm.TeamMember, *scm.Response, error) { - users, res, err := s.ListMemberUsers(ctx, org) + users, res, err := s.ListMemberUsers(ctx, org, ops) if err != nil { return nil, res, err } @@ -58,8 +75,8 @@ func (s *organizationService) ListOrgMembers(ctx context.Context, org string, op return members, res, nil } -func (s *organizationService) ListMemberUsers(ctx context.Context, org string) ([]scm.User, *scm.Response, error) { - path := fmt.Sprintf("api/v4/projects/%s/members/all", org) +func (s *organizationService) ListMemberUsers(ctx context.Context, org string, opts scm.ListOptions) ([]scm.User, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/members/all?%s", org, encodeListOptions(opts)) out := []*user{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertUserList(out), res, err @@ -79,6 +96,18 @@ func (s *organizationService) List(ctx context.Context, opts scm.ListOptions) ([ return convertOrganizationList(out), res, err } +func (s *organizationService) ListPendingInvitations(ctx context.Context, org string, opts scm.ListOptions) ([]*scm.OrganizationPendingInvite, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *organizationService) AcceptOrganizationInvitation(ctx context.Context, org string) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *organizationService) ListMemberships(ctx context.Context, opts scm.ListOptions) ([]*scm.Membership, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + type organization struct { ID int `json:"id"` Name string `json:"name"` diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/pr.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/pr.go index 44be32e70..730f1e9c3 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/pr.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/pr.go @@ -12,6 +12,8 @@ import ( "strings" "time" + "github.com/mitchellh/copystructure" + "github.com/jenkins-x/go-scm/scm" ) @@ -23,7 +25,14 @@ func (s *pullService) Find(ctx context.Context, repo string, number int) (*scm.P path := fmt.Sprintf("api/v4/projects/%s/merge_requests/%d", encode(repo), number) out := new(pr) res, err := s.client.do(ctx, "GET", path, nil, out) - return convertPullRequest(out), res, err + if err != nil { + return nil, res, err + } + convRepo, convRes, err := s.convertPullRequest(ctx, out) + if err != nil { + return nil, convRes, err + } + return convRepo, res, nil } func (s *pullService) FindComment(ctx context.Context, repo string, index, id int) (*scm.Comment, *scm.Response, error) { @@ -37,7 +46,14 @@ func (s *pullService) List(ctx context.Context, repo string, opts scm.PullReques path := fmt.Sprintf("api/v4/projects/%s/merge_requests?%s", encode(repo), encodePullRequestListOptions(opts)) out := []*pr{} res, err := s.client.do(ctx, "GET", path, nil, &out) - return convertPullRequestList(out), res, err + if err != nil { + return nil, res, err + } + convRepos, convRes, err := s.convertPullRequestList(ctx, out) + if err != nil { + return nil, convRes, err + } + return convRepos, res, nil } func (s *pullService) ListChanges(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Change, *scm.Response, error) { @@ -232,7 +248,14 @@ func (s *pullService) Create(ctx context.Context, repo string, input *scm.PullRe out := new(pr) res, err := s.client.do(ctx, "POST", path, in, out) - return convertPullRequest(out), res, err + if err != nil { + return nil, res, err + } + convRepo, convRes, err := s.convertPullRequest(ctx, out) + if err != nil { + return nil, convRes, err + } + return convRepo, res, nil } func (s *pullService) Update(ctx context.Context, repo string, number int, input *scm.PullRequestInput) (*scm.PullRequest, *scm.Response, error) { @@ -249,6 +272,23 @@ func (s *pullService) Update(ctx context.Context, repo string, number int, input return s.updateMergeRequestField(ctx, repo, number, updateOpts) } +func (s *pullService) SetMilestone(ctx context.Context, repo string, prID int, number int) (*scm.Response, error) { + updateOpts := &updateMergeRequestOptions{ + MilestoneID: &number, + } + _, res, err := s.updateMergeRequestField(ctx, repo, prID, updateOpts) + return res, err +} + +func (s *pullService) ClearMilestone(ctx context.Context, repo string, prID int) (*scm.Response, error) { + zeroVal := 0 + updateOpts := &updateMergeRequestOptions{ + MilestoneID: &zeroVal, + } + _, res, err := s.updateMergeRequestField(ctx, repo, prID, updateOpts) + return res, err +} + type updateMergeRequestOptions struct { Title *string `json:"title,omitempty"` Description *string `json:"description,omitempty"` @@ -269,7 +309,14 @@ func (s *pullService) updateMergeRequestField(ctx context.Context, repo string, out := new(pr) res, err := s.client.do(ctx, "PUT", path, input, out) - return convertPullRequest(out), res, err + if err != nil { + return nil, res, err + } + convRepo, convRes, err := s.convertPullRequest(ctx, out) + if err != nil { + return nil, convRes, err + } + return convRepo, res, nil } type pr struct { @@ -320,19 +367,26 @@ type prInput struct { type pullRequestMergeRequest struct { CommitMessage string `json:"merge_commit_message,omitempty"` + SquashCommitMessage string `json:"squash_commit_message,omitempty"` + Squash string `json:"squash,omitempty"` + RemoveSourceBranch string `json:"should_remove_source_branch,omitempty"` SHA string `json:"sha,omitempty"` MergeWhenPipelineSucceeds string `json:"merge_when_pipeline_succeeds,omitempty"` } -func convertPullRequestList(from []*pr) []*scm.PullRequest { +func (s *pullService) convertPullRequestList(ctx context.Context, from []*pr) ([]*scm.PullRequest, *scm.Response, error) { to := []*scm.PullRequest{} for _, v := range from { - to = append(to, convertPullRequest(v)) + converted, res, err := s.convertPullRequest(ctx, v) + if err != nil { + return nil, res, err + } + to = append(to, converted) } - return to + return to, nil, nil } -func convertPullRequest(from *pr) *scm.PullRequest { +func (s *pullService) convertPullRequest(ctx context.Context, from *pr) (*scm.PullRequest, *scm.Response, error) { // Diff refs only seem to be populated in more recent merge requests. Default // to from.Sha for compatibility / consistency, but fallback to HeadSHA if // it's not populated. @@ -347,6 +401,28 @@ func convertPullRequest(from *pr) *scm.PullRequest { for _, a := range from.Assignees { assignees = append(assignees, *convertUser(a)) } + var res *scm.Response + baseRepo, res, err := s.client.Repositories.Find(ctx, strconv.Itoa(from.TargetProjectID)) + if err != nil { + return nil, res, err + } + var headRepo *scm.Repository + if from.TargetProjectID == from.SourceProjectID { + repoCopy, err := copystructure.Copy(baseRepo) + if err != nil { + return nil, nil, err + } + headRepo = repoCopy.(*scm.Repository) + } else { + headRepo, res, err = s.client.Repositories.Find(ctx, strconv.Itoa(from.SourceProjectID)) + if err != nil { + return nil, res, err + } + } + sourceRepo, err := s.getSourceFork(ctx, from) + if err != nil { + return nil, res, err + } return &scm.PullRequest{ Number: from.Number, Title: from.Title, @@ -366,22 +442,29 @@ func convertPullRequest(from *pr) *scm.PullRequest { Author: *convertUser(&from.Author), Assignees: assignees, Head: scm.PullRequestBranch{ - Ref: from.SourceBranch, - Sha: headSHA, - Repo: scm.Repository{ - ID: strconv.Itoa(from.SourceProjectID), - }, + Ref: from.SourceBranch, + Sha: headSHA, + Repo: *headRepo, }, Base: scm.PullRequestBranch{ - Ref: from.TargetBranch, - Sha: from.DiffRefs.BaseSHA, - Repo: scm.Repository{ - ID: strconv.Itoa(from.TargetProjectID), - }, + Ref: from.TargetBranch, + Sha: from.DiffRefs.BaseSHA, + Repo: *baseRepo, }, Created: from.Created, Updated: from.Updated, + Fork: sourceRepo.PathNamespace, + }, nil, nil +} + +func (s *pullService) getSourceFork(ctx context.Context, from *pr) (repository, error) { + path := fmt.Sprintf("api/v4/projects/%d", from.SourceProjectID) + sourceRepo := repository{} + _, err := s.client.do(ctx, "GET", path, nil, &sourceRepo) + if err != nil { + return repository{}, err } + return sourceRepo, nil } func convertPullRequestLabels(from []*string) []*scm.Label { diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/release.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/release.go new file mode 100644 index 000000000..959963f62 --- /dev/null +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/release.go @@ -0,0 +1,111 @@ +package gitlab + +import ( + "context" + "fmt" + + "github.com/jenkins-x/go-scm/scm" +) + +type releaseService struct { + client *wrapper +} + +type release struct { + Title string `json:"name"` + Description string `json:"description"` + Tag string `json:"tag_name"` + Commit struct { + ID string `json:"id"` + } `json:"commit"` +} + +type releaseInput struct { + Title string `json:"name"` + Description string `json:"description"` + Tag string `json:"tag_name"` +} + +func (s *releaseService) Find(ctx context.Context, repo string, id int) (*scm.Release, *scm.Response, error) { + // this could be implemented by List and filter but would be to expensive + panic("gitlab only allows to find a release by tag") +} + +func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/releases/%s", encode(repo), tag) + out := new(release) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertRelease(out), res, err +} + +func (s *releaseService) List(ctx context.Context, repo string, opts scm.ReleaseListOptions) ([]*scm.Release, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/releases", encode(repo)) + out := []*release{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertReleaseList(out), res, err +} + +func (s *releaseService) Create(ctx context.Context, repo string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/releases", encode(repo)) + in := &releaseInput{ + Title: input.Title, + Description: input.Description, + Tag: input.Tag, + } + out := new(release) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertRelease(out), res, err +} + +func (s *releaseService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + // this could be implemented by List and filter but would be to expensive + panic("gitlab only allows to delete a release by tag") +} + +func (s *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/releases/%s", encode(repo), tag) + return s.client.do(ctx, "DELETE", path, nil, nil) +} + +func (s *releaseService) Update(ctx context.Context, repo string, id int, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + // this could be implemented by List and filter but would be to expensive + panic("gitlab only allows to update a release by tag") +} + +func (s *releaseService) UpdateByTag(ctx context.Context, repo string, tag string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/releases/%s", encode(repo), tag) + in := &releaseInput{} + if input.Title != "" { + in.Title = input.Title + } + if input.Description != "" { + in.Description = input.Description + } + if input.Tag != "" { + in.Tag = input.Tag + } + out := new(release) + res, err := s.client.do(ctx, "PUT", path, in, out) + return convertRelease(out), res, err +} + +func convertReleaseList(from []*release) []*scm.Release { + var to []*scm.Release + for _, m := range from { + to = append(to, convertRelease(m)) + } + return to +} + +func convertRelease(from *release) *scm.Release { + return &scm.Release{ + ID: 0, + Title: from.Title, + Description: from.Description, + Link: "", + Tag: from.Tag, + Commitish: from.Commit.ID, + Draft: false, // not supported by gitlab + Prerelease: false, // not supported by gitlab + } +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/repo.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/repo.go index 4dda71dc7..9de3f8db2 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/repo.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/repo.go @@ -61,7 +61,8 @@ type memberPermissions struct { func stringToAccessLevel(perm string) int { switch perm { case scm.AdminPermission: - return ownerPermissions + // owner permission only applies to groups, so fails for projects + return maintainerPermissions case scm.WritePermission: return developerPermissions case scm.ReadPermission: @@ -178,9 +179,22 @@ func (s *repositoryService) Fork(ctx context.Context, input *scm.RepositoryInput } func (s *repositoryService) FindCombinedStatus(ctx context.Context, repo, ref string) (*scm.CombinedStatus, *scm.Response, error) { - statuses, res, err := s.ListStatus(ctx, repo, ref, scm.ListOptions{}) - if err != nil { - return nil, res, err + var resp *scm.Response + var statuses []*scm.Status + var statusesByPage []*scm.Status + var err error + firstRun := false + opts := scm.ListOptions{ + Page: 1, + } + for !firstRun || (resp != nil && opts.Page <= resp.Page.Last) { + statusesByPage, resp, err = s.ListStatus(ctx, repo, ref, opts) + if err != nil { + return nil, resp, err + } + statuses = append(statuses, statusesByPage...) + firstRun = true + opts.Page++ } combinedState := scm.StateUnknown @@ -196,22 +210,32 @@ func (s *repositoryService) FindCombinedStatus(ctx context.Context, repo, ref st State: combinedState, Sha: ref, Statuses: statuses, - }, res, err + }, resp, err } func (s *repositoryService) FindUserPermission(ctx context.Context, repo string, user string) (string, *scm.Response, error) { - path := fmt.Sprintf("api/v4/projects/%s/members/all", encode(repo)) - out := []*member{} - res, err := s.client.do(ctx, "GET", path, nil, &out) - if err != nil { - return scm.NoPermission, res, err - } - for _, u := range out { - if u.Username == user { - return accessLevelToString(u.AccessLevel), res, nil + var resp *scm.Response + var err error + firstRun := false + opts := scm.ListOptions{ + Page: 1, + } + for !firstRun || (resp != nil && opts.Page <= resp.Page.Last) { + path := fmt.Sprintf("api/v4/projects/%s/members/all?%s", encode(repo), encodeListOptions(opts)) + out := []*member{} + resp, err = s.client.do(ctx, "GET", path, nil, &out) + if err != nil { + return scm.NoPermission, resp, err + } + firstRun = true + for _, u := range out { + if u.Username == user { + return accessLevelToString(u.AccessLevel), resp, nil + } } + opts.Page++ } - return scm.NoPermission, res, nil + return scm.NoPermission, resp, nil } func (s *repositoryService) AddCollaborator(ctx context.Context, repo, username, permission string) (bool, bool, *scm.Response, error) { @@ -236,14 +260,25 @@ func (s *repositoryService) AddCollaborator(ctx context.Context, repo, username, } func (s *repositoryService) IsCollaborator(ctx context.Context, repo, user string) (bool, *scm.Response, error) { - users, resp, err := s.ListCollaborators(ctx, repo, scm.ListOptions{}) - if err != nil { - return false, resp, err - } - for _, u := range users { - if u.Name == user || u.Login == user { - return true, resp, err + var resp *scm.Response + var users []scm.User + var err error + firstRun := false + opts := scm.ListOptions{ + Page: 1, + } + for !firstRun || (resp != nil && opts.Page <= resp.Page.Last) { + users, resp, err = s.ListCollaborators(ctx, repo, opts) + if err != nil { + return false, resp, err + } + firstRun = true + for _, u := range users { + if u.Name == user || u.Login == user { + return true, resp, err + } } + opts.Page++ } return false, resp, err } @@ -321,23 +356,29 @@ func (s *repositoryService) CreateHook(ctx context.Context, repo string, input * if input.SkipVerify { params.Set("enable_ssl_verification", "true") } + hasStarEvents := false + for _, event := range input.NativeEvents { + if event == "*" { + hasStarEvents = true + } + } if input.Events.Branch { // no-op } - if input.Events.Issue { + if input.Events.Issue || hasStarEvents { params.Set("issues_events", "true") } if input.Events.IssueComment || - input.Events.PullRequestComment { + input.Events.PullRequestComment || hasStarEvents { params.Set("note_events", "true") } - if input.Events.PullRequest { + if input.Events.PullRequest || hasStarEvents { params.Set("merge_requests_events", "true") } - if input.Events.Push || input.Events.Branch { + if input.Events.Push || input.Events.Branch || hasStarEvents { params.Set("push_events", "true") } - if input.Events.Tag { + if input.Events.Tag || hasStarEvents { params.Set("tag_push_events", "true") } @@ -364,6 +405,10 @@ func (s *repositoryService) DeleteHook(ctx context.Context, repo string, id stri return s.client.do(ctx, "DELETE", path, nil, nil) } +func (s *repositoryService) Delete(context.Context, string) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + // helper function to convert from the gogs repository list to // the common repository structure. func convertRepositoryList(from []*repository) []*scm.Repository { @@ -386,6 +431,7 @@ func convertRepository(from *repository) *scm.Repository { Private: convertPrivate(from.Visibility), Clone: from.HTTPURL, CloneSSH: from.SSHURL, + Link: from.WebURL, Perm: &scm.Perm{ Pull: true, Push: canPush(from), diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/user.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/user.go index 8a2629020..f1b6c69f5 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/user.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/user.go @@ -7,6 +7,7 @@ package gitlab import ( "context" "fmt" + "net/http" "strings" "github.com/jenkins-x/go-scm/scm" @@ -17,6 +18,14 @@ type userService struct { client *wrapper } +func (s *userService) CreateToken(context.Context, string, string) (*scm.UserToken, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *userService) DeleteToken(context.Context, int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + func (s *userService) Find(ctx context.Context) (*scm.User, *scm.Response, error) { out := new(user) res, err := s.client.do(ctx, "GET", "api/v4/user", nil, out) @@ -24,16 +33,42 @@ func (s *userService) Find(ctx context.Context) (*scm.User, *scm.Response, error } func (s *userService) FindLogin(ctx context.Context, login string) (*scm.User, *scm.Response, error) { - path := fmt.Sprintf("api/v4/users?search=%s", login) - out := []*user{} - res, err := s.client.do(ctx, "GET", path, nil, &out) + var resp *scm.Response + var err error + firstRun := false + opts := scm.ListOptions{ + Page: 1, + } + for !firstRun || (resp != nil && opts.Page <= resp.Page.Last) { + out := []*user{} + path := fmt.Sprintf("api/v4/users?search=%s&%s", login, encodeListOptions(opts)) + resp, err = s.client.do(ctx, "GET", path, nil, &out) + if err != nil { + return nil, nil, err + } + firstRun = true + for _, u := range out { + if strings.EqualFold(u.Username, login) { + return convertUser(u), resp, err + } + } + opts.Page++ + } + return nil, resp, scm.ErrNotFound +} + +// FindLoginByID returns the scm.User object for the specified user id +func (s *userService) FindLoginByID(ctx context.Context, id int) (*scm.User, error) { + path := fmt.Sprintf("api/v4/users/%d", id) + out := &user{} + resp, err := s.client.do(ctx, "GET", path, nil, &out) if err != nil { - return nil, nil, err + return nil, err } - if len(out) != 1 || !strings.EqualFold(out[0].Username, login) { - return nil, nil, scm.ErrNotFound + if resp.Status == http.StatusOK { + return convertUser(out), err } - return convertUser(out[0]), res, err + return nil, scm.ErrNotFound } func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, error) { diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/util.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/util.go index b2fb782e3..6ede52ca4 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/util.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/util.go @@ -24,6 +24,12 @@ func encodeListOptions(opts scm.ListOptions) string { if opts.Size != 0 { params.Set("per_page", strconv.Itoa(opts.Size)) } + if opts.From != "" { + params.Set("from", opts.From) + } + if opts.To != "" { + params.Set("to", opts.To) + } return params.Encode() } @@ -71,6 +77,22 @@ func encodeIssueListOptions(opts scm.IssueListOptions) string { return params.Encode() } +func encodeMilestoneListOptions(opts scm.MilestoneListOptions) string { + params := url.Values{} + if opts.Page != 0 { + params.Set("page", strconv.Itoa(opts.Page)) + } + if opts.Size != 0 { + params.Set("per_page", strconv.Itoa(opts.Size)) + } + if opts.Closed && !opts.Open { + params.Set("state", "closed") + } else if opts.Open && !opts.Closed { + params.Set("state", "active") + } + return params.Encode() +} + func encodePullRequestListOptions(opts scm.PullRequestListOptions) string { params := url.Values{} if opts.Page != 0 { @@ -111,12 +133,24 @@ func encodePullRequestMergeOptions(opts *scm.PullRequestMergeOptions) *pullReque if opts.SHA != "" { prRequest.SHA = opts.SHA } + switch opts.MergeMethod { + case "squash": + if opts.CommitTitle != "" { + prRequest.SquashCommitMessage = opts.CommitTitle + } + prRequest.Squash = "true" + default: + if opts.CommitTitle != "" { + prRequest.CommitMessage = opts.CommitTitle + } + } if opts.MergeWhenPipelineSucceeds { prRequest.MergeWhenPipelineSucceeds = "true" } - if opts.CommitTitle != "" { - prRequest.CommitMessage = opts.CommitTitle + if opts.DeleteSourceBranch { + prRequest.RemoveSourceBranch = "true" } + } return prRequest } diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/webhook.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/webhook.go index cba49ba59..11c8ea1bc 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/webhook.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gitlab/webhook.go @@ -5,6 +5,7 @@ package gitlab import ( + "context" "crypto/subtle" "encoding/json" "fmt" @@ -19,6 +20,13 @@ import ( type webhookService struct { client *wrapper + //need the user service as well + userService webhookUserService +} + +// an interface to provide a find login by id in gitlab +type webhookUserService interface { + FindLoginByID(ctx context.Context, id int) (*scm.User, error) } func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhook, error) { @@ -35,13 +43,13 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo case "Push Hook", "Tag Push Hook": hook, err = parsePushHook(data) case "Issue Hook": - return nil, scm.UnknownWebhook{event} + return nil, scm.UnknownWebhook{Event: event} case "Merge Request Hook": hook, err = parsePullRequestHook(data) case "Note Hook": - hook, err = parseCommentHook(data) + hook, err = parseCommentHook(s, data) default: - return nil, scm.UnknownWebhook{event} + return nil, scm.UnknownWebhook{Event: event} } if err != nil { return nil, err @@ -103,7 +111,7 @@ func parsePullRequestHook(data []byte) (scm.Webhook, error) { case "open", "close", "reopen", "merge", "update": // no-op default: - return nil, scm.UnknownWebhook{event} + return nil, scm.UnknownWebhook{Event: event} } switch { default: @@ -111,7 +119,7 @@ func parsePullRequestHook(data []byte) (scm.Webhook, error) { } } -func parseCommentHook(data []byte) (scm.Webhook, error) { +func parseCommentHook(s *webhookService, data []byte) (scm.Webhook, error) { src := new(commentHook) err := json.Unmarshal(data, src) if err != nil { @@ -123,17 +131,18 @@ func parseCommentHook(data []byte) (scm.Webhook, error) { kind := src.ObjectAttributes.NoteableType switch kind { case "MergeRequest": - return convertMergeRequestCommentHook(src), nil + return convertMergeRequestCommentHook(s, src) default: - return nil, scm.UnknownWebhook{kind} + return nil, scm.UnknownWebhook{Event: kind} } } func convertPushHook(src *pushHook) *scm.PushHook { repo := *convertRepositoryHook(&src.Project) dst := &scm.PushHook{ - Ref: scm.ExpandRef(src.Ref, "refs/heads/"), - Repo: repo, + Ref: scm.ExpandRef(src.Ref, "refs/heads/"), + Repo: repo, + After: src.After, Commit: scm.Commit{ Sha: src.CheckoutSha, Message: "", // NOTE this is set below @@ -264,6 +273,13 @@ func convertPullRequestHook(src *pullRequestHook) *scm.PullRequestHook { } pr.Base.Repo = *convertRepositoryHook(src.ObjectAttributes.Target) pr.Head.Repo = *convertRepositoryHook(src.ObjectAttributes.Source) + changes := scm.PullRequestHookChanges{ + Base: scm.PullRequestHookBranch{ + Sha: scm.PullRequestHookBranchFrom{ + From: src.ObjectAttributes.OldRev, + }, + }, + } return &scm.PullRequestHook{ Action: action, PullRequest: pr, @@ -274,16 +290,22 @@ func convertPullRequestHook(src *pullRequestHook) *scm.PullRequestHook { Email: "", // TODO how do we get the pull request author email? Avatar: src.User.AvatarURL, }, + Changes: changes, } } -func convertMergeRequestCommentHook(src *commentHook) *scm.PullRequestCommentHook { - user := scm.User{ - ID: src.ObjectAttributes.AuthorID, - Login: src.User.Username, - Name: src.User.Name, - Email: "", // TODO how do we get the pull request author email? - Avatar: src.User.AvatarURL, +func convertMergeRequestCommentHook(s *webhookService, src *commentHook) (*scm.PullRequestCommentHook, error) { + + // There are two users needed here: the comment author and the MergeRequest author. + // Since we only have the user name, we need to use the user service to fetch these. + commentAuthor, err := s.userService.FindLoginByID(context.TODO(), src.ObjectAttributes.AuthorID) + if err != nil { + return nil, fmt.Errorf("unable to find comment author %w", err) + } + + mrAuthor, err := s.userService.FindLoginByID(context.TODO(), src.MergeRequest.AuthorID) + if err != nil { + return nil, fmt.Errorf("unable to find mr author %w", err) } fork := scm.Join( @@ -297,8 +319,8 @@ func convertMergeRequestCommentHook(src *commentHook) *scm.PullRequestCommentHoo sha := src.MergeRequest.LastCommit.ID // Mon Jan 2 15:04:05 -0700 MST 2006 - created_pr_at, _ := time.Parse("2006-01-02 15:04:05 MST", src.MergeRequest.CreatedAt) - updated_pr_at, _ := time.Parse("2006-01-02 15:04:05 MST", src.MergeRequest.UpdatedAt) + prCreatedAt, _ := time.Parse("2006-01-02 15:04:05 MST", src.MergeRequest.CreatedAt) + prUpdatedAt, _ := time.Parse("2006-01-02 15:04:05 MST", src.MergeRequest.UpdatedAt) pr := scm.PullRequest{ Number: src.MergeRequest.Iid, Title: src.MergeRequest.Title, @@ -319,29 +341,30 @@ func convertMergeRequestCommentHook(src *commentHook) *scm.PullRequestCommentHoo Link: src.MergeRequest.URL, Closed: src.MergeRequest.State != "opened", Merged: src.MergeRequest.State == "merged", - Created: created_pr_at, - Updated: updated_pr_at, // 2017-12-10 17:01:11 UTC - Author: user, + Created: prCreatedAt, + Updated: prUpdatedAt, // 2017-12-10 17:01:11 UTC + Author: *mrAuthor, } pr.Base.Repo = *convertRepositoryHook(src.MergeRequest.Target) pr.Head.Repo = *convertRepositoryHook(src.MergeRequest.Source) - created_at, _ := time.Parse("2006-01-02 15:04:05 MST", src.ObjectAttributes.CreatedAt) - updated_at, _ := time.Parse("2006-01-02 15:04:05 MST", src.ObjectAttributes.UpdatedAt) + createdAt, _ := time.Parse("2006-01-02 15:04:05 MST", src.ObjectAttributes.CreatedAt) + updatedAt, _ := time.Parse("2006-01-02 15:04:05 MST", src.ObjectAttributes.UpdatedAt) - return &scm.PullRequestCommentHook{ + hook := &scm.PullRequestCommentHook{ Action: scm.ActionCreate, Repo: repo, PullRequest: pr, Comment: scm.Comment{ ID: src.ObjectAttributes.ID, Body: src.ObjectAttributes.Note, - Author: user, // TODO: is the user the author id ?? - Created: created_at, - Updated: updated_at, + Author: *commentAuthor, + Created: createdAt, + Updated: updatedAt, }, - Sender: user, + Sender: *commentAuthor, } + return hook, nil } func convertRepositoryHook(from *project) *scm.Repository { @@ -706,6 +729,7 @@ type ( HumanTotalTimeSpent interface{} `json:"human_total_time_spent"` HumanTimeEstimate interface{} `json:"human_time_estimate"` Action string `json:"action"` + OldRev string `json:"oldrev"` } `json:"object_attributes"` Labels []interface{} `json:"labels"` Changes struct { diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/git.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/git.go index eed21bd1b..8a958eea0 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/git.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/git.go @@ -65,6 +65,10 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.Li return nil, nil, scm.ErrNotSupported } +func (s *gitService) CompareCommits(ctx context.Context, repo, ref1, ref2 string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + // // native data structures // diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/gogs.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/gogs.go index 85ab2f936..eb62f8b05 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/gogs.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/gogs.go @@ -18,6 +18,7 @@ import ( "github.com/jenkins-x/go-scm/scm" ) +// NewWebHookService creates a new instance of the webhook service without the rest of the client func NewWebHookService() scm.WebhookService { return &webhookService{nil} } @@ -38,6 +39,7 @@ func New(uri string) (*scm.Client, error) { client.Contents = &contentService{client} client.Git = &gitService{client} client.Issues = &issueService{client} + client.Milestones = &milestoneService{client} client.Organizations = &organizationService{client} client.PullRequests = &pullService{client} client.Repositories = &repositoryService{client} @@ -64,7 +66,7 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface // write it to the body of the request. if in != nil { buf := new(bytes.Buffer) - json.NewEncoder(buf).Encode(in) + json.NewEncoder(buf).Encode(in) // #nosec req.Header = map[string][]string{ "Content-Type": {"application/json"}, } @@ -93,8 +95,8 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface // if raw output is expected, copy to the provided // buffer and exit. if w, ok := out.(io.Writer); ok { - io.Copy(w, res.Body) - return res, nil + _, err := io.Copy(w, res.Body) + return res, err } // if a json response is expected, parse and return diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/issue.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/issue.go index 27025aeac..531e8601a 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/issue.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/issue.go @@ -116,6 +116,14 @@ func (s *issueService) Unlock(ctx context.Context, repo string, number int) (*sc return nil, scm.ErrNotSupported } +func (s *issueService) SetMilestone(ctx context.Context, repo string, issueID int, number int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *issueService) ClearMilestone(ctx context.Context, repo string, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + // // native data structures // diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/milestone.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/milestone.go new file mode 100644 index 000000000..5758e571a --- /dev/null +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/milestone.go @@ -0,0 +1,31 @@ +package gogs + +import ( + "context" + + "github.com/jenkins-x/go-scm/scm" +) + +type milestoneService struct { + client *wrapper +} + +func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *milestoneService) List(ctx context.Context, repo string, opts scm.MilestoneListOptions) ([]*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/org.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/org.go index 2a8b4bd9f..bd2cd2420 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/org.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/org.go @@ -15,6 +15,14 @@ type organizationService struct { client *wrapper } +func (s *organizationService) Create(context.Context, *scm.OrganizationInput) (*scm.Organization, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *organizationService) Delete(context.Context, string) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + func (s *organizationService) IsMember(ctx context.Context, org string, user string) (bool, *scm.Response, error) { return false, nil, scm.ErrNotSupported } @@ -48,6 +56,18 @@ func (s *organizationService) List(ctx context.Context, _ scm.ListOptions) ([]*s return convertOrgList(out), res, err } +func (s *organizationService) ListPendingInvitations(ctx context.Context, org string, opts scm.ListOptions) ([]*scm.OrganizationPendingInvite, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *organizationService) AcceptOrganizationInvitation(ctx context.Context, org string) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *organizationService) ListMemberships(ctx context.Context, opts scm.ListOptions) ([]*scm.Membership, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + // // native data structures // diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/pr.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/pr.go index 452ea7b11..101534e21 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/pr.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/pr.go @@ -99,6 +99,14 @@ func (s *pullService) UnrequestReview(ctx context.Context, repo string, number i return nil, scm.ErrNotSupported } +func (s *pullService) SetMilestone(ctx context.Context, repo string, prID int, number int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *pullService) ClearMilestone(ctx context.Context, repo string, prID int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + // // native data structures // diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/repo.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/repo.go index c5a450d35..45f036387 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/repo.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/repo.go @@ -127,6 +127,10 @@ func (s *repositoryService) DeleteHook(ctx context.Context, repo string, id stri return s.client.do(ctx, "DELETE", path, nil, nil) } +func (s *repositoryService) Delete(context.Context, string) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + // // native data structures // diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/user.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/user.go index 2b1de51cf..c521332cb 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/user.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/user.go @@ -15,6 +15,14 @@ type userService struct { client *wrapper } +func (s *userService) CreateToken(context.Context, string, string) (*scm.UserToken, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *userService) DeleteToken(context.Context, int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + func (s *userService) Find(ctx context.Context) (*scm.User, *scm.Response, error) { out := new(user) res, err := s.client.do(ctx, "GET", "api/v1/user", nil, out) diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/webhook.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/webhook.go index f73bec522..62a4dee3c 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/webhook.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/gogs/webhook.go @@ -44,7 +44,7 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo case "pull_request": hook, err = s.parsePullRequestHook(data) default: - return nil, scm.UnknownWebhook{event} + return nil, scm.UnknownWebhook{Event: event} } if err != nil { return nil, err @@ -87,7 +87,7 @@ func (s *webhookService) parseCreateHook(data []byte) (scm.Webhook, error) { case "branch": return convertBranchHook(dst, scm.ActionCreate), err default: - return nil, scm.UnknownWebhook{dst.RefType} + return nil, scm.UnknownWebhook{Event: dst.RefType} } } @@ -100,7 +100,7 @@ func (s *webhookService) parseDeleteHook(data []byte) (scm.Webhook, error) { case "branch": return convertBranchHook(dst, scm.ActionDelete), err default: - return nil, scm.UnknownWebhook{dst.RefType} + return nil, scm.UnknownWebhook{Event: dst.RefType} } } diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/content.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/content.go index f6e1eecf6..147cd59fb 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/content.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/content.go @@ -8,6 +8,7 @@ import ( "bytes" "context" "fmt" + "net/url" "github.com/jenkins-x/go-scm/scm" ) @@ -18,7 +19,7 @@ type contentService struct { func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm.Content, *scm.Response, error) { namespace, name := scm.Split(repo) - endpoint := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/raw/%s?at=%s", namespace, name, path, ref) + endpoint := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/raw/%s?at=%s", namespace, name, path, url.QueryEscape(ref)) buf := new(bytes.Buffer) res, err := s.client.do(ctx, "GET", endpoint, nil, buf) return &scm.Content{ diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/git.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/git.go index 6d9a6295f..1b8ca2b1b 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/git.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/git.go @@ -7,6 +7,7 @@ package stash import ( "context" "fmt" + "net/url" "strings" "time" @@ -23,7 +24,7 @@ type gitService struct { func (s *gitService) FindRef(ctx context.Context, repo, ref string) (string, *scm.Response, error) { ref = strings.TrimPrefix(ref, "heads/") namespace, name := scm.Split(repo) - path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/commits/%s", namespace, name, ref) + path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/commits/%s", namespace, name, url.PathEscape(ref)) out := commit{} res, err := s.client.do(ctx, "GET", path, nil, &out) if err != nil { @@ -49,7 +50,7 @@ func (s *gitService) DeleteRef(ctx context.Context, repo, ref string) (*scm.Resp func (s *gitService) FindBranch(ctx context.Context, repo, branch string) (*scm.Reference, *scm.Response, error) { namespace, name := scm.Split(repo) - path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/branches?filterText=%s", namespace, name, branch) + path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/branches?filterText=%s", namespace, name, url.QueryEscape(branch)) out := new(branches) res, err := s.client.do(ctx, "GET", path, nil, out) if err != nil { @@ -65,7 +66,7 @@ func (s *gitService) FindBranch(ctx context.Context, repo, branch string) (*scm. func (s *gitService) FindCommit(ctx context.Context, repo, ref string) (*scm.Commit, *scm.Response, error) { namespace, name := scm.Split(repo) - path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/commits/%s", namespace, name, ref) + path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/commits/%s", namespace, name, url.PathEscape(ref)) out := new(commit) res, err := s.client.do(ctx, "GET", path, nil, out) return convertCommit(out), res, err @@ -73,7 +74,7 @@ func (s *gitService) FindCommit(ctx context.Context, repo, ref string) (*scm.Com func (s *gitService) FindTag(ctx context.Context, repo, tag string) (*scm.Reference, *scm.Response, error) { namespace, name := scm.Split(repo) - path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/tags?filterText=%s", namespace, name, tag) + path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/tags?filterText=%s", namespace, name, url.QueryEscape(tag)) out := new(branches) res, err := s.client.do(ctx, "GET", path, nil, out) if err != nil { @@ -117,7 +118,21 @@ func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOpt func (s *gitService) ListChanges(ctx context.Context, repo, ref string, opts scm.ListOptions) ([]*scm.Change, *scm.Response, error) { namespace, name := scm.Split(repo) - path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/commits/%s/changes?%s", namespace, name, ref, encodeListOptions(opts)) + path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/commits/%s/changes?%s", namespace, name, url.PathEscape(ref), encodeListOptions(opts)) + out := new(diffstats) + res, err := s.client.do(ctx, "GET", path, nil, &out) + if !out.pagination.LastPage.Bool { + res.Page.First = 1 + res.Page.Next = opts.Page + 1 + } + return convertDiffstats(out), res, err +} + +func (s *gitService) CompareCommits(ctx context.Context, repo, ref1, ref2 string, opts scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + namespace, name := scm.Split(repo) + opts.From = url.PathEscape(ref1) + opts.To = url.PathEscape(ref2) + path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/compare/changes?%s", namespace, name, encodeListOptions(opts)) out := new(diffstats) res, err := s.client.do(ctx, "GET", path, nil, &out) if !out.pagination.LastPage.Bool { diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/issue.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/issue.go index b34a7b97f..d2a87c43b 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/issue.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/issue.go @@ -8,6 +8,8 @@ import ( "context" "fmt" + "github.com/jenkins-x/go-scm/scm/labels" + "github.com/jenkins-x/go-scm/scm" ) @@ -31,16 +33,26 @@ func (s *issueService) ListEvents(context.Context, string, int, scm.ListOptions) return nil, nil, scm.ErrNotSupported } -func (s *issueService) ListLabels(context.Context, string, int, scm.ListOptions) ([]*scm.Label, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported +func (s *issueService) ListLabels(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Label, *scm.Response, error) { + // Get all comments, parse out labels (removing and added based off time) + cs, res, err := s.ListComments(ctx, repo, number, opts) + if err == nil { + l, err := labels.ConvertLabelComments(cs) + return l, res, err + } + return nil, res, err } func (s *issueService) AddLabel(ctx context.Context, repo string, number int, label string) (*scm.Response, error) { - return nil, scm.ErrNotSupported + input := labels.CreateLabelAddComment(label) + _, res, err := s.CreateComment(ctx, repo, number, input) + return res, err } func (s *issueService) DeleteLabel(ctx context.Context, repo string, number int, label string) (*scm.Response, error) { - return nil, scm.ErrNotSupported + input := labels.CreateLabelRemoveComment(label) + _, res, err := s.CreateComment(ctx, repo, number, input) + return res, err } func (s *issueService) Find(ctx context.Context, repo string, number int) (*scm.Issue, *scm.Response, error) { @@ -95,3 +107,11 @@ func (s *issueService) Lock(ctx context.Context, repo string, number int) (*scm. func (s *issueService) Unlock(ctx context.Context, repo string, number int) (*scm.Response, error) { return nil, scm.ErrNotSupported } + +func (s *issueService) SetMilestone(ctx context.Context, repo string, issueID int, number int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *issueService) ClearMilestone(ctx context.Context, repo string, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/milestone.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/milestone.go new file mode 100644 index 000000000..6ec3c2a97 --- /dev/null +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/milestone.go @@ -0,0 +1,31 @@ +package stash + +import ( + "context" + + "github.com/jenkins-x/go-scm/scm" +) + +type milestoneService struct { + client *wrapper +} + +func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *milestoneService) List(ctx context.Context, repo string, opts scm.MilestoneListOptions) ([]*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/org.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/org.go index 14c4e252b..967cc4329 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/org.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/org.go @@ -15,6 +15,26 @@ type organizationService struct { client *wrapper } +type project struct { + ID int `json:"id,omitempty"` + Key string `json:"key"` + Name string `json:"name"` + Description string `json:"description"` +} + +type projectResponse struct { + pagination + Values []project `json:"values"` +} + +func (s *organizationService) Create(context.Context, *scm.OrganizationInput) (*scm.Organization, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *organizationService) Delete(context.Context, string) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + func (s *organizationService) ListTeams(ctx context.Context, org string, ops scm.ListOptions) ([]*scm.Team, *scm.Response, error) { return nil, nil, scm.ErrNotSupported } @@ -80,6 +100,21 @@ func (s *organizationService) Find(ctx context.Context, name string) (*scm.Organ } func (s *organizationService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Organization, *scm.Response, error) { + path := fmt.Sprintf("rest/api/1.0/projects?%s", encodeListOptions(opts)) + out := new(projectResponse) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertProjectList(out.Values), res, err +} + +func (s *organizationService) ListPendingInvitations(ctx context.Context, org string, opts scm.ListOptions) ([]*scm.OrganizationPendingInvite, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *organizationService) AcceptOrganizationInvitation(ctx context.Context, org string) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *organizationService) ListMemberships(ctx context.Context, opts scm.ListOptions) ([]*scm.Membership, *scm.Response, error) { return nil, nil, scm.ErrNotSupported } @@ -90,3 +125,24 @@ func convertParticipantsToTeamMembers(from *participants) []*scm.TeamMember { } return teamMembers } + +func convertProjectList(from []project) []*scm.Organization { + var to []*scm.Organization + for _, v := range from { + to = append(to, convertProject(v)) + } + return to +} + +func convertProject(from project) *scm.Organization { + return &scm.Organization{ + ID: from.ID, + Name: from.Key, + Avatar: "", + Permissions: scm.Permissions{ + MembersCreateInternal: true, + MembersCreatePublic: true, + MembersCreatePrivate: true, + }, + } +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/pr.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/pr.go index 39a84a84b..5014ae0ce 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/pr.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/pr.go @@ -8,9 +8,12 @@ import ( "context" "fmt" "net/http" + "net/url" "strings" "time" + "github.com/jenkins-x/go-scm/scm/labels" + "github.com/jenkins-x/go-scm/scm" ) @@ -59,19 +62,29 @@ func (s *pullService) ListChanges(ctx context.Context, repo string, number int, } func (s *pullService) ListLabels(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Label, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported -} - -func (s *pullService) ListEvents(context.Context, string, int, scm.ListOptions) ([]*scm.ListedIssueEvent, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + // Get all comments, parse out labels (removing and added based off time) + cs, res, err := s.ListComments(ctx, repo, number, opts) + if err == nil { + l, err := labels.ConvertLabelComments(cs) + return l, res, err + } + return nil, res, err } func (s *pullService) AddLabel(ctx context.Context, repo string, number int, label string) (*scm.Response, error) { - return nil, scm.ErrNotSupported + input := labels.CreateLabelAddComment(label) + _, res, err := s.CreateComment(ctx, repo, number, input) + return res, err } func (s *pullService) DeleteLabel(ctx context.Context, repo string, number int, label string) (*scm.Response, error) { - return nil, scm.ErrNotSupported + input := labels.CreateLabelRemoveComment(label) + _, res, err := s.CreateComment(ctx, repo, number, input) + return res, err +} + +func (s *pullService) ListEvents(context.Context, string, int, scm.ListOptions) ([]*scm.ListedIssueEvent, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported } func (s *pullService) ListComments(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Comment, *scm.Response, error) { @@ -251,7 +264,7 @@ func (s *pullService) RequestReview(ctx context.Context, repo string, number int Approved: false, Status: "UNAPPROVED", } - path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/pull-requests/%d/participants/%s", namespace, name, number, l) + path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/pull-requests/%d/participants/%s", namespace, name, number, url.PathEscape(l)) res, err = s.client.do(ctx, "PUT", path, &input, nil) if err != nil && res != nil { missing.Users = append(missing.Users, l) @@ -271,7 +284,7 @@ func (s *pullService) UnrequestReview(ctx context.Context, repo string, number i var err error for _, l := range logins { - path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/pull-requests/%d/participants/%s", namespace, name, number, l) + path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/pull-requests/%d/participants/%s", namespace, name, number, url.PathEscape(l)) res, err = s.client.do(ctx, "DELETE", path, nil, nil) if err != nil { return nil, fmt.Errorf("failed to add reviewer to PR. errmsg: %v", err) @@ -280,6 +293,14 @@ func (s *pullService) UnrequestReview(ctx context.Context, repo string, number i return res, err } +func (s *pullService) SetMilestone(ctx context.Context, repo string, prID int, number int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *pullService) ClearMilestone(ctx context.Context, repo string, prID int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + type createPRInput struct { Title string `json:"title,omitempty"` Description string `json:"description,omitempty"` diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/repo.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/repo.go index 779b19cb2..61feaf045 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/repo.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/repo.go @@ -161,7 +161,7 @@ func (s *repositoryService) Fork(ctx context.Context, input *scm.RepositoryInput } func (s *repositoryService) FindCombinedStatus(ctx context.Context, repo, ref string) (*scm.CombinedStatus, *scm.Response, error) { - path := fmt.Sprintf("rest/build-status/1.0/commits/%s?orderBy=oldest", ref) + path := fmt.Sprintf("rest/build-status/1.0/commits/%s?orderBy=oldest", url.PathEscape(ref)) out := new(statuses) res, err := s.client.do(ctx, "GET", path, nil, &out) @@ -203,7 +203,7 @@ func (s *repositoryService) FindCombinedStatus(ctx context.Context, repo, ref st func (s *repositoryService) FindUserPermission(ctx context.Context, repo string, user string) (string, *scm.Response, error) { namespace, name := scm.Split(repo) - path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/permissions/users?filter=%s", namespace, name, user) + path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/permissions/users?filter=%s", namespace, name, url.QueryEscape(user)) out := new(participants) res, err := s.client.do(ctx, "GET", path, nil, out) if err != nil { @@ -231,7 +231,7 @@ func (s *repositoryService) AddCollaborator(ctx context.Context, repo, user, per return false, false, nil, fmt.Errorf("unknown permission '%s'", permission) } namespace, name := scm.Split(repo) - path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/permissions/users", namespace, name) + path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/permissions/users?&name=%s&permission=%s", namespace, name, user, apiPerm) input := &addCollaboratorInput{ Name: user, Permission: apiPerm, @@ -380,7 +380,7 @@ func (s *repositoryService) ListHooks(ctx context.Context, repo string, opts scm // ListStatus returns a list of commit statuses. func (s *repositoryService) ListStatus(ctx context.Context, _, ref string, opts scm.ListOptions) ([]*scm.Status, *scm.Response, error) { - path := fmt.Sprintf("rest/build-status/1.0/commits/%s?%s", ref, encodeListOptions(opts)) + path := fmt.Sprintf("rest/build-status/1.0/commits/%s?%s", url.PathEscape(ref), encodeListOptions(opts)) out := new(statuses) res, err := s.client.do(ctx, "GET", path, nil, &out) if !out.pagination.LastPage.Bool { @@ -411,7 +411,7 @@ func (s *repositoryService) CreateHook(ctx context.Context, repo string, input * // CreateStatus creates a new commit status. // reference: https://developer.atlassian.com/server/bitbucket/how-tos/updating-build-status-for-commits/ func (s *repositoryService) CreateStatus(ctx context.Context, repo, ref string, input *scm.StatusInput) (*scm.Status, *scm.Response, error) { - path := fmt.Sprintf("rest/build-status/1.0/commits/%s", ref) + path := fmt.Sprintf("rest/build-status/1.0/commits/%s", url.PathEscape(ref)) in := status{ State: convertFromState(input.State), Key: input.Label, @@ -435,6 +435,10 @@ func (s *repositoryService) DeleteHook(ctx context.Context, repo string, id stri return s.client.do(ctx, "DELETE", path, nil, nil) } +func (s *repositoryService) Delete(context.Context, string) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + // helper function to convert from the gogs repository list to // the common repository structure. func convertRepositoryList(from *repositories) []*scm.Repository { @@ -515,6 +519,7 @@ func convertHookEvents(from scm.HookEvents) []string { events = append(events, "pr:deleted") events = append(events, "pr:opened") events = append(events, "pr:merged") + events = append(events, "pr:from_ref_updated") } if from.PullRequestComment { events = append(events, "pr:comment:added") diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/stash.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/stash.go index 3778b0af7..88ab1bf1d 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/stash.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/stash.go @@ -20,6 +20,7 @@ import ( // Reference API Documentation: // https://docs.atlassian.com/bitbucket-server/rest/5.11.1/bitbucket-rest.html +// NewWebHookService creates a new instance of the webhook service without the rest of the client func NewWebHookService() scm.WebhookService { return &webhookService{nil} } @@ -40,6 +41,7 @@ func New(uri string) (*scm.Client, error) { client.Contents = &contentService{client} client.Git = &gitService{client} client.Issues = &issueService{client} + client.Milestones = &milestoneService{client} client.Organizations = &organizationService{client} client.PullRequests = &pullService{client} client.Repositories = &repositoryService{client} @@ -73,7 +75,7 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface // write it to the body of the request. if in != nil { buf := new(bytes.Buffer) - json.NewEncoder(buf).Encode(in) + json.NewEncoder(buf).Encode(in) // #nosec req.Header.Add("Content-Type", "application/json") req.Body = buf } @@ -92,7 +94,7 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface return res, scm.ErrNotAuthorized } else if res.Status > 300 { err := new(Error) - json.NewDecoder(res.Body).Decode(err) + json.NewDecoder(res.Body).Decode(err) // #nosec return res, err } @@ -103,8 +105,8 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface // if raw output is expected, copy to the provided // buffer and exit. if w, ok := out.(io.Writer); ok { - io.Copy(w, res.Body) - return res, nil + _, err := io.Copy(w, res.Body) + return res, err } // if a json response is expected, parse and return diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/user.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/user.go index 0ae9df492..8f8d11e99 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/user.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/user.go @@ -7,9 +7,10 @@ package stash import ( "bytes" "context" - "crypto/md5" + "crypto/md5" // #nosec "encoding/hex" "fmt" + "net/url" "strings" "github.com/jenkins-x/go-scm/scm" @@ -19,6 +20,14 @@ type userService struct { client *wrapper } +func (s *userService) CreateToken(context.Context, string, string) (*scm.UserToken, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *userService) DeleteToken(context.Context, int64) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + func (s *userService) Find(ctx context.Context) (*scm.User, *scm.Response, error) { path := fmt.Sprintf("plugins/servlet/applinks/whoami") out := new(bytes.Buffer) @@ -32,7 +41,7 @@ func (s *userService) Find(ctx context.Context) (*scm.User, *scm.Response, error } func (s *userService) FindLogin(ctx context.Context, login string) (*scm.User, *scm.Response, error) { - path := fmt.Sprintf("rest/api/1.0/users/%s", login) + path := fmt.Sprintf("rest/api/1.0/users/%s", url.PathEscape(login)) out := new(user) res, err := s.client.do(ctx, "GET", path, nil, out) return convertUser(out), res, err @@ -48,11 +57,13 @@ func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, err } func (s *userService) ListInvitations(context.Context) ([]*scm.Invitation, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + // bitbucket server does not have an invite concept, so always return successfully + return []*scm.Invitation{}, &scm.Response{Status: 200}, nil } func (s *userService) AcceptInvitation(context.Context, int64) (*scm.Response, error) { - return nil, scm.ErrNotSupported + // bitbucket server does not have an invite concept, so always return successfully + return &scm.Response{Status: 200}, nil } type user struct { @@ -83,8 +94,8 @@ func convertUser(from *user) *scm.User { } func avatarLink(email string) string { - hasher := md5.New() - hasher.Write([]byte(strings.ToLower(email))) + hasher := md5.New() // #nosec + hasher.Write([]byte(strings.ToLower(email))) // #nosec emailHash := fmt.Sprintf("%v", hex.EncodeToString(hasher.Sum(nil))) avatarURL := fmt.Sprintf("https://www.gravatar.com/avatar/%s.jpg", emailHash) return avatarURL diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/util.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/util.go index 9b4fd87ff..90c0ccef8 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/util.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/util.go @@ -21,6 +21,12 @@ func encodeListOptions(opts scm.ListOptions) string { if opts.Size != 0 { params.Set("limit", strconv.Itoa(opts.Size)) } + if opts.From != "" { + params.Set("from", opts.From) + } + if opts.To != "" { + params.Set("to", opts.To) + } return params.Encode() } diff --git a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/webhook.go b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/webhook.go index 2af82940d..4673628c2 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/webhook.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/driver/stash/webhook.go @@ -51,7 +51,7 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo case "pr:reviewer:approved", "pr:reviewer:unapproved", "pr:reviewer:needs_work": hook, err = s.parsePullRequestApproval(data) default: - return nil, scm.UnknownWebhook{event} + return nil, scm.UnknownWebhook{Event: event} } if err != nil { return nil, err @@ -224,15 +224,17 @@ func convertPushHook(src *pushHook) *scm.PushHook { sender := convertUser(src.Actor) signer := convertSignature(src.Actor) signer.Date, _ = time.Parse("2006-01-02T15:04:05+0000", src.Date) + sha := change.ToHash return &scm.PushHook{ Ref: change.RefID, Commit: scm.Commit{ - Sha: change.ToHash, + Sha: sha, Message: "", Link: "", Author: signer, Committer: signer, }, + After: sha, Repo: *repo, Sender: *sender, } diff --git a/vendor/github.com/jenkins-x/go-scm/scm/factory/factory.go b/vendor/github.com/jenkins-x/go-scm/scm/factory/factory.go index 910859862..d30920368 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/factory/factory.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/factory/factory.go @@ -8,6 +8,8 @@ import ( "os" "strings" + "github.com/pkg/errors" + "github.com/jenkins-x/go-scm/scm" "github.com/jenkins-x/go-scm/scm/driver/bitbucket" "github.com/jenkins-x/go-scm/scm/driver/fake" @@ -20,16 +22,52 @@ import ( "golang.org/x/oauth2" ) -// MissingGitServerURL the error returned if you use a git driver that needs a git server URL -var MissingGitServerURL = fmt.Errorf("No git serverURL was specified") +// ErrMissingGitServerURL the error returned if you use a git driver that needs a git server URL +var ErrMissingGitServerURL = fmt.Errorf("No git serverURL was specified") // DefaultIdentifier is the default driver identifier used by FromRepoURL. var DefaultIdentifier = NewDriverIdentifier() -type clientOptionFunc func(*scm.Client) +// ClientOptionFunc is a function taking a client as its argument +type ClientOptionFunc func(*scm.Client) + +// SetUsername allows the username to be set +func SetUsername(username string) ClientOptionFunc { + return func(client *scm.Client) { + if username != "" { + client.Username = username + } + } +} + +// NewClientWithBasicAuth creates a new client for a given driver, serverURL and basic auth +func NewClientWithBasicAuth(driver, serverURL, user, password string, opts ...ClientOptionFunc) (*scm.Client, error) { + if driver == "" { + driver = "github" + } + var client *scm.Client + var err error + + switch driver { + case "gitea": + if serverURL == "" { + return nil, ErrMissingGitServerURL + } + client, err = gitea.NewWithBasicAuth(serverURL, user, password) + default: + return nil, fmt.Errorf("Unsupported $GIT_KIND value: %s", driver) + } + if err != nil { + return client, err + } + for _, o := range opts { + o(client) + } + return client, err +} // NewClient creates a new client for a given driver, serverURL and OAuth token -func NewClient(driver, serverURL, oauthToken string, opts ...clientOptionFunc) (*scm.Client, error) { +func NewClient(driver, serverURL, oauthToken string, opts ...ClientOptionFunc) (*scm.Client, error) { if driver == "" { driver = "github" } @@ -47,9 +85,9 @@ func NewClient(driver, serverURL, oauthToken string, opts ...clientOptionFunc) ( client, _ = fake.NewDefault() case "gitea": if serverURL == "" { - return nil, MissingGitServerURL + return nil, ErrMissingGitServerURL } - client, err = gitea.New(serverURL) + client, err = gitea.NewWithToken(serverURL, oauthToken) case "github": if serverURL != "" { client, err = github.New(ensureGHEEndpoint(serverURL)) @@ -64,12 +102,12 @@ func NewClient(driver, serverURL, oauthToken string, opts ...clientOptionFunc) ( } case "gogs": if serverURL == "" { - return nil, MissingGitServerURL + return nil, ErrMissingGitServerURL } client, err = gogs.New(serverURL) case "stash", "bitbucketserver": if serverURL == "" { - return nil, MissingGitServerURL + return nil, ErrMissingGitServerURL } client, err = stash.New(serverURL) default: @@ -79,13 +117,36 @@ func NewClient(driver, serverURL, oauthToken string, opts ...clientOptionFunc) ( return client, err } if oauthToken != "" { - if driver == "gitlab" || driver == "bitbucketcloud" { + switch driver { + case "gitea": + client.Client = &http.Client{ + Transport: &transport.Authorization{ + Scheme: "token", + Credentials: oauthToken, + }, + } + case "gitlab": client.Client = &http.Client{ Transport: &transport.PrivateToken{ Token: oauthToken, }, } - } else { + case "bitbucketcloud": + // lets process any options now so that we can populate the username + for _, o := range opts { + o(client) + } + if client.Username == "" { + return nil, errors.Errorf("no username supplied") + } + client.Client = &http.Client{ + Transport: &transport.BasicAuth{ + Username: client.Username, + Password: oauthToken, + }, + } + return client, nil + default: ts := oauth2.StaticTokenSource( &oauth2.Token{AccessToken: oauthToken}, ) @@ -107,10 +168,15 @@ func NewClientFromEnvironment() (*scm.Client, error) { driver := os.Getenv("GIT_KIND") serverURL := os.Getenv("GIT_SERVER") oauthToken := os.Getenv("GIT_TOKEN") + username := os.Getenv("GIT_USER") + if username == "" { + username = os.Getenv("GIT_USERNAME") + } + if oauthToken == "" { return nil, fmt.Errorf("No Git OAuth token specified for $GIT_TOKEN") } - client, err := NewClient(driver, serverURL, oauthToken) + client, err := NewClient(driver, serverURL, oauthToken, SetUsername(username)) if driver == "" { driver = client.Driver.String() } @@ -146,7 +212,7 @@ func ensureGHEEndpoint(u string) string { } // lets ensure we use the API endpoint to login if !strings.Contains(u, "/api/") { - u = scm.UrlJoin(u, "/api/v3") + u = scm.URLJoin(u, "/api/v3") } return u } @@ -159,17 +225,19 @@ func ensureBBCEndpoint(u string) string { return u } -func Client(httpClient *http.Client) clientOptionFunc { +// Client creates a new client with the given HTTP client +func Client(httpClient *http.Client) ClientOptionFunc { return func(c *scm.Client) { c.Client = httpClient } } +// NewWebHookService creates a new instance of the webhook service without the rest of the client func NewWebHookService(driver string) (scm.WebhookService, error) { if driver == "" { driver = "github" } - var service scm.WebhookService = nil + var service scm.WebhookService switch driver { case "bitbucket", "bitbucketcloud": service = bitbucket.NewWebHookService() diff --git a/vendor/github.com/jenkins-x/go-scm/scm/git.go b/vendor/github.com/jenkins-x/go-scm/scm/git.go index d391bcf54..e6663c290 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/git.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/git.go @@ -74,9 +74,12 @@ type ( // ListCommits returns a list of git commits. ListCommits(ctx context.Context, repo string, opts CommitListOptions) ([]*Commit, *Response, error) - // ListChanges returns the changeset between two commits. + // ListChanges returns the changeset between a commit and its parent. ListChanges(ctx context.Context, repo, ref string, opts ListOptions) ([]*Change, *Response, error) + // ListChanges returns the changeset between two commits. + CompareCommits(ctx context.Context, repo, ref1, ref2 string, opts ListOptions) ([]*Change, *Response, error) + // ListTags returns a list of git tags. ListTags(ctx context.Context, repo string, opts ListOptions) ([]*Reference, *Response, error) diff --git a/vendor/github.com/jenkins-x/go-scm/scm/issue.go b/vendor/github.com/jenkins-x/go-scm/scm/issue.go index 4378b1a79..8d2080c04 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/issue.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/issue.go @@ -23,6 +23,7 @@ type ( Locked bool Author User Assignees []User + ClosedBy *User PullRequest bool Created time.Time Updated time.Time @@ -140,6 +141,12 @@ type ( // UnassignIssue removes the assignment of ne or more users on an issue UnassignIssue(ctx context.Context, repo string, number int, logins []string) (*Response, error) + + // SetMilestone adds a milestone to an issue + SetMilestone(ctx context.Context, repo string, issueID int, number int) (*Response, error) + + // ClearMilestone removes the milestone from an issue + ClearMilestone(ctx context.Context, repo string, id int) (*Response, error) } ) diff --git a/vendor/github.com/jenkins-x/go-scm/scm/labels/labels.go b/vendor/github.com/jenkins-x/go-scm/scm/labels/labels.go new file mode 100644 index 000000000..ba0391f01 --- /dev/null +++ b/vendor/github.com/jenkins-x/go-scm/scm/labels/labels.go @@ -0,0 +1,56 @@ +package labels + +import ( + "fmt" + "sort" + "strings" + + "github.com/jenkins-x/go-scm/scm" +) + +const ( + addLabel = "/jx-label " + removeLabel = " remove" + emptyString = "" +) + +// ConvertLabelComments converts comments to labels for git providers which don't support native labels +func ConvertLabelComments(cs []*scm.Comment) ([]*scm.Label, error) { + sort.SliceStable(cs, func(i, j int) bool { + return cs[i].Created.UnixNano() < cs[j].Created.UnixNano() + }) + m := make(map[string]bool) + for _, com := range cs { + if strings.HasPrefix(com.Body, addLabel) { + t := strings.ReplaceAll(com.Body, addLabel, emptyString) + if strings.HasSuffix(t, removeLabel) { + t = strings.ReplaceAll(t, removeLabel, emptyString) + m[t] = true + } else { + m[t] = false + } + } + } + var ls []*scm.Label + for l, i := range m { + if i == false { + ls = append(ls, &scm.Label{Name: l}) + } + } + return ls, nil +} + +// CreateLabelAddComment creates a label comment for git providers which don't support labels with comment with /jx-label +func CreateLabelAddComment(label string) *scm.CommentInput { + return &scm.CommentInput{ + Body: fmt.Sprintf("%s%s", addLabel, label), + } +} + +// CreateLabelRemoveComment adds a comment with /jx-label remove +func CreateLabelRemoveComment(label string) *scm.CommentInput { + input := &scm.CommentInput{ + Body: fmt.Sprintf("%s%s%s", addLabel, label, removeLabel), + } + return input +} diff --git a/vendor/github.com/jenkins-x/go-scm/scm/milestone.go b/vendor/github.com/jenkins-x/go-scm/scm/milestone.go new file mode 100644 index 000000000..54ed9683b --- /dev/null +++ b/vendor/github.com/jenkins-x/go-scm/scm/milestone.go @@ -0,0 +1,42 @@ +package scm + +import ( + "context" + "time" +) + +type ( + // MilestoneInput contains the information needed to create a milestone + MilestoneInput struct { + Title string + Description string + State string + DueDate *time.Time + } + + // MilestoneListOptions provides options for querying a list of repository milestones. + MilestoneListOptions struct { + Page int + Size int + Open bool + Closed bool + } + + // MilestoneService provides access to creating, listing, updating, and deleting milestones + MilestoneService interface { + // Find returns the milestone for the given number in the given repository + Find(context.Context, string, int) (*Milestone, *Response, error) + + // List returns a list of milestones in the given repository + List(context.Context, string, MilestoneListOptions) ([]*Milestone, *Response, error) + + // Create creates a milestone in the given repository + Create(context.Context, string, *MilestoneInput) (*Milestone, *Response, error) + + // Update updates a milestone in the given repository + Update(context.Context, string, int, *MilestoneInput) (*Milestone, *Response, error) + + // Delete deletes a milestone in the given repository + Delete(context.Context, string, int) (*Response, error) + } +) diff --git a/vendor/github.com/jenkins-x/go-scm/scm/org.go b/vendor/github.com/jenkins-x/go-scm/scm/org.go index 5e63e2c51..9547b0e69 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/org.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/org.go @@ -17,6 +17,23 @@ type ( Permissions Permissions } + // OrganizationPendingInvite represents a pending invite to an organisation + OrganizationPendingInvite struct { + ID int + Login string + InviterLogin string + } + + // OrganizationInput provides the input fields required for + // creating a new organization. + OrganizationInput struct { + Name string + Description string + Homepage string + Private bool + } + + // Permissions represents the possible permissions a user can have on an org Permissions struct { MembersCreatePrivate bool MembersCreatePublic bool @@ -43,11 +60,24 @@ type ( IsAdmin bool `json:"isAdmin,omitempty"` } + // Membership describes the membership a user has to an organisation + Membership struct { + State string + Role string + OrganizationName string + } + // OrganizationService provides access to organization resources. OrganizationService interface { // Find returns the organization by name. Find(context.Context, string) (*Organization, *Response, error) + // Create creates an organization. + Create(context.Context, *OrganizationInput) (*Organization, *Response, error) + + // Delete deletes an organization. + Delete(context.Context, string) (*Response, error) + // List returns the user organization list. List(context.Context, ListOptions) ([]*Organization, *Response, error) @@ -65,5 +95,14 @@ type ( // ListOrgMembers lists the members of the organization ListOrgMembers(ctx context.Context, org string, ops ListOptions) ([]*TeamMember, *Response, error) + + // ListPendingInvitations lists the pending invitations for an organisation + ListPendingInvitations(ctx context.Context, org string, ops ListOptions) ([]*OrganizationPendingInvite, *Response, error) + + // AcceptPendingInvitation accepts a pending invitation for an organisation + AcceptOrganizationInvitation(ctx context.Context, org string) (*Response, error) + + // ListMemberships lists organisation memberships for the authenticated user + ListMemberships(ctx context.Context, opts ListOptions) ([]*Membership, *Response, error) } ) diff --git a/vendor/github.com/jenkins-x/go-scm/scm/pr.go b/vendor/github.com/jenkins-x/go-scm/scm/pr.go index 9833b4c9c..9225a40d9 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/pr.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/pr.go @@ -11,6 +11,7 @@ import ( ) type ( + // MergeableState represents whether the PR can be merged MergeableState string // PullRequest represents a repository pull request. @@ -48,6 +49,7 @@ type ( DiffLink string } + // PullRequestInput provides the input needed to create or update a PR. PullRequestInput struct { Title string Head string @@ -55,7 +57,7 @@ type ( Body string } - // Milestone the milestotne + // Milestone the milestone Milestone struct { Number int ID int @@ -63,6 +65,19 @@ type ( Description string Link string State string + DueDate *time.Time + } + + // Release the release + Release struct { + ID int + Title string + Description string + Link string + Tag string + Commitish string + Draft bool + Prerelease bool } // PullRequestListOptions provides options for querying @@ -111,6 +126,9 @@ type ( // Merge automatically once the pipeline completes. (Supported only in gitlab) MergeWhenPipelineSucceeds bool + + // Signals to the SCM to remove the source branch during merge + DeleteSourceBranch bool } // PullRequestService provides access to pull request resources. @@ -177,6 +195,12 @@ type ( // UnrequestReview removes one or more users as a reviewer on a pull request. UnrequestReview(ctx context.Context, repo string, number int, logins []string) (*Response, error) + + // SetMilestone adds a milestone to a pull request + SetMilestone(ctx context.Context, repo string, prID int, number int) (*Response, error) + + // ClearMilestone removes the milestone from a pull request + ClearMilestone(ctx context.Context, repo string, prID int) (*Response, error) } ) diff --git a/vendor/github.com/jenkins-x/go-scm/scm/release.go b/vendor/github.com/jenkins-x/go-scm/scm/release.go new file mode 100644 index 000000000..023d5ae1f --- /dev/null +++ b/vendor/github.com/jenkins-x/go-scm/scm/release.go @@ -0,0 +1,52 @@ +package scm + +import ( + "context" +) + +type ( + // ReleaseInput contains the information needed to create a release + ReleaseInput struct { + Title string + Description string + Tag string + Commitish string + Draft bool + Prerelease bool + } + + // ReleaseListOptions provides options for querying a list of repository releases. + ReleaseListOptions struct { + Page int + Size int + Open bool + Closed bool + } + + // ReleaseService provides access to creating, listing, updating, and deleting releases + ReleaseService interface { + // Find returns the release for the given number in the given repository + Find(context.Context, string, int) (*Release, *Response, error) + + // FindByTag returns the release for the given tag in the given repository + FindByTag(context.Context, string, string) (*Release, *Response, error) + + // List returns a list of releases in the given repository + List(context.Context, string, ReleaseListOptions) ([]*Release, *Response, error) + + // Create creates a release in the given repository + Create(context.Context, string, *ReleaseInput) (*Release, *Response, error) + + // Update updates a release in the given repository + Update(context.Context, string, int, *ReleaseInput) (*Release, *Response, error) + + // Update updates a release in the given repository by tag + UpdateByTag(context.Context, string, string, *ReleaseInput) (*Release, *Response, error) + + // Delete deletes a release in the given repository + Delete(context.Context, string, int) (*Response, error) + + // Delete deletes a release in the given repository by tag + DeleteByTag(context.Context, string, string) (*Response, error) + } +) diff --git a/vendor/github.com/jenkins-x/go-scm/scm/repo.go b/vendor/github.com/jenkins-x/go-scm/scm/repo.go index 27a1076c1..bff1b3f39 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/repo.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/repo.go @@ -87,6 +87,7 @@ type ( PullRequest bool PullRequestComment bool Push bool + Review bool ReviewComment bool Tag bool } @@ -175,6 +176,9 @@ type ( // FindUserPermission returns the user's permission level for a repo FindUserPermission(ctx context.Context, repo string, user string) (string, *Response, error) + + // Delete deletes a repository + Delete(ctx context.Context, repo string) (*Response, error) } ) diff --git a/vendor/github.com/jenkins-x/go-scm/scm/review.go b/vendor/github.com/jenkins-x/go-scm/scm/review.go index 7ba485b97..548e222dd 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/review.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/review.go @@ -97,9 +97,14 @@ type ( ) const ( - ReviewStateApproved string = "APPROVED" + // ReviewStateApproved is used for approved reviews + ReviewStateApproved string = "APPROVED" + // ReviewStateChangesRequested is used for reviews with changes requested ReviewStateChangesRequested string = "CHANGES_REQUESTED" - ReviewStateCommented string = "COMMENTED" - ReviewStateDismissed string = "DISMISSED" - ReviewStatePending string = "PENDING" + // ReviewStateCommented is used for reviews with comments + ReviewStateCommented string = "COMMENTED" + // ReviewStateDismissed is used for reviews that have been dismissed + ReviewStateDismissed string = "DISMISSED" + // ReviewStatePending is used for reviews that are awaiting response + ReviewStatePending string = "PENDING" ) diff --git a/vendor/github.com/jenkins-x/go-scm/scm/user.go b/vendor/github.com/jenkins-x/go-scm/scm/user.go index 912389cc9..d2b445012 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/user.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/user.go @@ -18,10 +18,17 @@ type ( Email string Avatar string Link string + IsAdmin bool `json:"isAdmin,omitempty"` Created time.Time Updated time.Time } + // UserToken represents a user token. + UserToken struct { + ID int64 + Token string + } + // Invitation represents a repo invitation Invitation struct { ID int64 @@ -38,6 +45,12 @@ type ( // Find returns the authenticated user. Find(context.Context) (*User, *Response, error) + // CreateToken creates a user token. + CreateToken(context.Context, string, string) (*UserToken, *Response, error) + + // DeleteToken deletes a user token. + DeleteToken(context.Context, int64) (*Response, error) + // FindEmail returns the authenticated user email. FindEmail(context.Context) (string, *Response, error) diff --git a/vendor/github.com/jenkins-x/go-scm/scm/util.go b/vendor/github.com/jenkins-x/go-scm/scm/util.go index c693414e6..16edb60af 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/util.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/util.go @@ -27,8 +27,8 @@ func Join(owner, name string) string { return owner + "/" + name } -// UrlJoin joins the given paths so that there is only ever one '/' character between the paths -func UrlJoin(paths ...string) string { +// URLJoin joins the given paths so that there is only ever one '/' character between the paths +func URLJoin(paths ...string) string { var buffer strings.Builder last := len(paths) - 1 for i, path := range paths { diff --git a/vendor/github.com/jenkins-x/go-scm/scm/webhook.go b/vendor/github.com/jenkins-x/go-scm/scm/webhook.go index 34b8d45af..b997b3d18 100644 --- a/vendor/github.com/jenkins-x/go-scm/scm/webhook.go +++ b/vendor/github.com/jenkins-x/go-scm/scm/webhook.go @@ -10,32 +10,56 @@ import ( "time" ) +// WebhookKind is the kind of webhook event represented type WebhookKind string const ( - WebhookKindBranch WebhookKind = "branch" - WebhookKindCheckRun WebhookKind = "check_run" - WebhookKindCheckSuite WebhookKind = "check_suite" - WebhookKindDeploy WebhookKind = "deploy" - WebhookKindDeploymentStatus WebhookKind = "deployment_status" - WebhookKindFork WebhookKind = "fork" - WebhookKindInstallation WebhookKind = "installation" + // WebhookKindBranch is for branch events + WebhookKindBranch WebhookKind = "branch" + // WebhookKindCheckRun is for check run events + WebhookKindCheckRun WebhookKind = "check_run" + // WebhookKindCheckSuite is for check suite events + WebhookKindCheckSuite WebhookKind = "check_suite" + // WebhookKindDeploy is for deploy events + WebhookKindDeploy WebhookKind = "deploy" + // WebhookKindDeploymentStatus is for deployment status events + WebhookKindDeploymentStatus WebhookKind = "deployment_status" + // WebhookKindFork is for fork events + WebhookKindFork WebhookKind = "fork" + // WebhookKindInstallation is for app installation events + WebhookKindInstallation WebhookKind = "installation" + // WebhookKindInstallationRepository is for app isntallation in a repository events WebhookKindInstallationRepository WebhookKind = "installation_repository" - WebhookKindIssue WebhookKind = "issue" - WebhookKindIssueComment WebhookKind = "issue_comment" - WebhookKindLabel WebhookKind = "label" - WebhookKindPing WebhookKind = "ping" - WebhookKindPullRequest WebhookKind = "pull_request" - WebhookKindPullRequestComment WebhookKind = "pull_request_comment" - WebhookKindPush WebhookKind = "push" - WebhookKindRelease WebhookKind = "release" - WebhookKindRepository WebhookKind = "repository" - WebhookKindReview WebhookKind = "review" - WebhookKindReviewCommentHook WebhookKind = "review_comment" - WebhookKindStar WebhookKind = "star" - WebhookKindStatus WebhookKind = "status" - WebhookKindTag WebhookKind = "tag" - WebhookKindWatch WebhookKind = "watch" + // WebhookKindIssue is for issue events + WebhookKindIssue WebhookKind = "issue" + // WebhookKindIssueComment is for issue comment events + WebhookKindIssueComment WebhookKind = "issue_comment" + // WebhookKindLabel is for label events + WebhookKindLabel WebhookKind = "label" + // WebhookKindPing is for ping events + WebhookKindPing WebhookKind = "ping" + // WebhookKindPullRequest is for pull request events + WebhookKindPullRequest WebhookKind = "pull_request" + // WebhookKindPullRequestComment is for pull request comment events + WebhookKindPullRequestComment WebhookKind = "pull_request_comment" + // WebhookKindPush is for push events + WebhookKindPush WebhookKind = "push" + // WebhookKindRelease is for release events + WebhookKindRelease WebhookKind = "release" + // WebhookKindRepository is for repository events + WebhookKindRepository WebhookKind = "repository" + // WebhookKindReview is for review events + WebhookKindReview WebhookKind = "review" + // WebhookKindReviewCommentHook is for review comment events + WebhookKindReviewCommentHook WebhookKind = "review_comment" + // WebhookKindStar is for star events + WebhookKindStar WebhookKind = "star" + // WebhookKindStatus is for status events + WebhookKindStatus WebhookKind = "status" + // WebhookKindTag is for tag events + WebhookKindTag WebhookKind = "tag" + // WebhookKindWatch is for watch events + WebhookKindWatch WebhookKind = "watch" ) var ( @@ -124,15 +148,30 @@ type ( Installation *InstallationRef } - // DeploymentStatusHook represents a check suite event - DeploymentStatusHook struct { + // DeployHook represents a deployment event. + // This is currently a GitHub-specific event type. + DeployHook struct { + Deployment Deployment Action Action + Ref Reference Repo Repository Sender User Label Label Installation *InstallationRef } + // DeploymentStatusHook represents a deployment status event. + // This is currently a GitHub-specific event type. + DeploymentStatusHook struct { + Deployment Deployment + DeploymentStatus DeploymentStatus + Action Action + Repo Repository + Sender User + Label Label + Installation *InstallationRef + } + // ForkHook represents a fork event ForkHook struct { Repo Repository @@ -236,16 +275,19 @@ type ( Link string } + // PullRequestHookBranchFrom represents the branch or ref a PR is from PullRequestHookBranchFrom struct { From string } + // PullRequestHookBranch represents a branch in a PR PullRequestHookBranch struct { Ref PullRequestHookBranchFrom Sha PullRequestHookBranchFrom Repo Repository } + // PullRequestHookChanges represents the changes in a PR PullRequestHookChanges struct { Base PullRequestHookBranch } @@ -284,20 +326,6 @@ type ( Installation *InstallationRef } - // DeployHook represents a deployment event. This is - // currently a GitHub-specific event type. - DeployHook struct { - Data interface{} - Desc string - Ref Reference - Repo Repository - Sender User - Target string - TargetURL string - Task string - Installation *InstallationRef - } - // WatchHook represents a watch event. This is currently GitHub-specific. WatchHook struct { Action string @@ -326,58 +354,161 @@ type ( } ) -// Kind() returns the kind of webhook - -func (h *PingHook) Kind() WebhookKind { return WebhookKindPing } -func (h *PushHook) Kind() WebhookKind { return WebhookKindPush } -func (h *BranchHook) Kind() WebhookKind { return WebhookKindBranch } -func (h *DeployHook) Kind() WebhookKind { return WebhookKindDeploy } -func (h *TagHook) Kind() WebhookKind { return WebhookKindTag } -func (h *IssueHook) Kind() WebhookKind { return WebhookKindIssue } -func (h *IssueCommentHook) Kind() WebhookKind { return WebhookKindIssueComment } -func (h *PullRequestHook) Kind() WebhookKind { return WebhookKindPullRequest } -func (h *PullRequestCommentHook) Kind() WebhookKind { return WebhookKindPullRequestComment } -func (h *ReviewHook) Kind() WebhookKind { return WebhookKindReview } -func (h *ReviewCommentHook) Kind() WebhookKind { return WebhookKindReviewCommentHook } -func (h *InstallationHook) Kind() WebhookKind { return WebhookKindInstallation } -func (h *LabelHook) Kind() WebhookKind { return WebhookKindLabel } -func (h *StatusHook) Kind() WebhookKind { return WebhookKindStatus } -func (h *CheckRunHook) Kind() WebhookKind { return WebhookKindCheckRun } -func (h *CheckSuiteHook) Kind() WebhookKind { return WebhookKindCheckSuite } -func (h *DeploymentStatusHook) Kind() WebhookKind { return WebhookKindDeploymentStatus } -func (h *ReleaseHook) Kind() WebhookKind { return WebhookKindRelease } -func (h *RepositoryHook) Kind() WebhookKind { return WebhookKindRepository } -func (h *ForkHook) Kind() WebhookKind { return WebhookKindFork } +// Kind returns the kind of webhook +func (h *PingHook) Kind() WebhookKind { return WebhookKindPing } + +// Kind returns the kind of webhook +func (h *PushHook) Kind() WebhookKind { return WebhookKindPush } + +// Kind returns the kind of webhook +func (h *BranchHook) Kind() WebhookKind { return WebhookKindBranch } + +// Kind returns the kind of webhook +func (h *DeployHook) Kind() WebhookKind { return WebhookKindDeploy } + +// Kind returns the kind of webhook +func (h *TagHook) Kind() WebhookKind { return WebhookKindTag } + +// Kind returns the kind of webhook +func (h *IssueHook) Kind() WebhookKind { return WebhookKindIssue } + +// Kind returns the kind of webhook +func (h *IssueCommentHook) Kind() WebhookKind { return WebhookKindIssueComment } + +// Kind returns the kind of webhook +func (h *PullRequestHook) Kind() WebhookKind { return WebhookKindPullRequest } + +// Kind returns the kind of webhook +func (h *PullRequestCommentHook) Kind() WebhookKind { return WebhookKindPullRequestComment } + +// Kind returns the kind of webhook +func (h *ReviewHook) Kind() WebhookKind { return WebhookKindReview } + +// Kind returns the kind of webhook +func (h *ReviewCommentHook) Kind() WebhookKind { return WebhookKindReviewCommentHook } + +// Kind returns the kind of webhook +func (h *InstallationHook) Kind() WebhookKind { return WebhookKindInstallation } + +// Kind returns the kind of webhook +func (h *LabelHook) Kind() WebhookKind { return WebhookKindLabel } + +// Kind returns the kind of webhook +func (h *StatusHook) Kind() WebhookKind { return WebhookKindStatus } + +// Kind returns the kind of webhook +func (h *CheckRunHook) Kind() WebhookKind { return WebhookKindCheckRun } + +// Kind returns the kind of webhook +func (h *CheckSuiteHook) Kind() WebhookKind { return WebhookKindCheckSuite } + +// Kind returns the kind of webhook +func (h *DeploymentStatusHook) Kind() WebhookKind { return WebhookKindDeploymentStatus } + +// Kind returns the kind of webhook +func (h *ReleaseHook) Kind() WebhookKind { return WebhookKindRelease } + +// Kind returns the kind of webhook +func (h *RepositoryHook) Kind() WebhookKind { return WebhookKindRepository } + +// Kind returns the kind of webhook +func (h *ForkHook) Kind() WebhookKind { return WebhookKindFork } + +// Kind returns the kind of webhook func (h *InstallationRepositoryHook) Kind() WebhookKind { return WebhookKindInstallationRepository } -func (h *WatchHook) Kind() WebhookKind { return WebhookKindWatch } -func (h *StarHook) Kind() WebhookKind { return WebhookKindStar } -// Repository() defines the repository webhook and provides -// a convenient way to get the associated repository without +// Kind returns the kind of webhook +func (h *WatchHook) Kind() WebhookKind { return WebhookKindWatch } + +// Kind returns the kind of webhook +func (h *StarHook) Kind() WebhookKind { return WebhookKindStar } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. +func (h *PingHook) Repository() Repository { return h.Repo } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. +func (h *PushHook) Repository() Repository { return h.Repo } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. +func (h *BranchHook) Repository() Repository { return h.Repo } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. +func (h *DeployHook) Repository() Repository { return h.Repo } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. +func (h *TagHook) Repository() Repository { return h.Repo } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without // having to cast the type. +func (h *IssueHook) Repository() Repository { return h.Repo } -func (h *PingHook) Repository() Repository { return h.Repo } -func (h *PushHook) Repository() Repository { return h.Repo } -func (h *BranchHook) Repository() Repository { return h.Repo } -func (h *DeployHook) Repository() Repository { return h.Repo } -func (h *TagHook) Repository() Repository { return h.Repo } -func (h *IssueHook) Repository() Repository { return h.Repo } -func (h *IssueCommentHook) Repository() Repository { return h.Repo } -func (h *PullRequestHook) Repository() Repository { return h.Repo } +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. +func (h *IssueCommentHook) Repository() Repository { return h.Repo } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. +func (h *PullRequestHook) Repository() Repository { return h.Repo } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. func (h *PullRequestCommentHook) Repository() Repository { return h.Repo } -func (h *ReviewCommentHook) Repository() Repository { return h.Repo } -func (h *ReviewHook) Repository() Repository { return h.Repo } -func (h *LabelHook) Repository() Repository { return h.Repo } -func (h *StatusHook) Repository() Repository { return h.Repo } -func (h *CheckRunHook) Repository() Repository { return h.Repo } -func (h *CheckSuiteHook) Repository() Repository { return h.Repo } -func (h *DeploymentStatusHook) Repository() Repository { return h.Repo } -func (h *ReleaseHook) Repository() Repository { return h.Repo } -func (h *RepositoryHook) Repository() Repository { return h.Repo } -func (h *ForkHook) Repository() Repository { return h.Repo } -func (h *WatchHook) Repository() Repository { return h.Repo } -func (h *StarHook) Repository() Repository { return h.Repo } +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. +func (h *ReviewCommentHook) Repository() Repository { return h.Repo } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. +func (h *ReviewHook) Repository() Repository { return h.Repo } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. +func (h *LabelHook) Repository() Repository { return h.Repo } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. +func (h *StatusHook) Repository() Repository { return h.Repo } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. +func (h *CheckRunHook) Repository() Repository { return h.Repo } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. +func (h *CheckSuiteHook) Repository() Repository { return h.Repo } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. +func (h *DeploymentStatusHook) Repository() Repository { return h.Repo } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. +func (h *ReleaseHook) Repository() Repository { return h.Repo } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. +func (h *RepositoryHook) Repository() Repository { return h.Repo } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. +func (h *ForkHook) Repository() Repository { return h.Repo } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. +func (h *WatchHook) Repository() Repository { return h.Repo } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. +func (h *StarHook) Repository() Repository { return h.Repo } + +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. func (h *InstallationHook) Repository() Repository { if len(h.Repos) > 0 { return *h.Repos[0] @@ -385,6 +516,8 @@ func (h *InstallationHook) Repository() Repository { return Repository{} } +// Repository defines the repository webhook and provides a convenient way to get the associated repository without +// having to cast the type. func (h *InstallationRepositoryHook) Repository() Repository { if len(h.ReposAdded) > 0 { return *h.ReposAdded[0] @@ -392,30 +525,92 @@ func (h *InstallationRepositoryHook) Repository() Repository { return Repository{} } -// GetInstallationRef() returns the installation reference if the webhook is invoked on a +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *PingHook) GetInstallationRef() *InstallationRef { return h.Installation } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *PushHook) GetInstallationRef() *InstallationRef { return h.Installation } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *BranchHook) GetInstallationRef() *InstallationRef { return h.Installation } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *DeployHook) GetInstallationRef() *InstallationRef { return h.Installation } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *TagHook) GetInstallationRef() *InstallationRef { return h.Installation } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *IssueHook) GetInstallationRef() *InstallationRef { return h.Installation } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *IssueCommentHook) GetInstallationRef() *InstallationRef { return h.Installation } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *PullRequestHook) GetInstallationRef() *InstallationRef { return h.Installation } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a // GitHub App -func (h *PingHook) GetInstallationRef() *InstallationRef { return h.Installation } -func (h *PushHook) GetInstallationRef() *InstallationRef { return h.Installation } -func (h *BranchHook) GetInstallationRef() *InstallationRef { return h.Installation } -func (h *DeployHook) GetInstallationRef() *InstallationRef { return h.Installation } -func (h *TagHook) GetInstallationRef() *InstallationRef { return h.Installation } -func (h *IssueHook) GetInstallationRef() *InstallationRef { return h.Installation } -func (h *IssueCommentHook) GetInstallationRef() *InstallationRef { return h.Installation } -func (h *PullRequestHook) GetInstallationRef() *InstallationRef { return h.Installation } func (h *PullRequestCommentHook) GetInstallationRef() *InstallationRef { return h.Installation } -func (h *ReviewHook) GetInstallationRef() *InstallationRef { return h.Installation } -func (h *ReviewCommentHook) GetInstallationRef() *InstallationRef { return h.Installation } -func (h *LabelHook) GetInstallationRef() *InstallationRef { return h.Installation } -func (h *StatusHook) GetInstallationRef() *InstallationRef { return h.Installation } -func (h *CheckRunHook) GetInstallationRef() *InstallationRef { return h.Installation } -func (h *CheckSuiteHook) GetInstallationRef() *InstallationRef { return h.Installation } -func (h *DeploymentStatusHook) GetInstallationRef() *InstallationRef { return h.Installation } -func (h *ReleaseHook) GetInstallationRef() *InstallationRef { return h.Installation } -func (h *RepositoryHook) GetInstallationRef() *InstallationRef { return h.Installation } -func (h *ForkHook) GetInstallationRef() *InstallationRef { return h.Installation } -func (h *WatchHook) GetInstallationRef() *InstallationRef { return h.Installation } -func (h *StarHook) GetInstallationRef() *InstallationRef { return nil } +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *ReviewHook) GetInstallationRef() *InstallationRef { return h.Installation } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *ReviewCommentHook) GetInstallationRef() *InstallationRef { return h.Installation } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *LabelHook) GetInstallationRef() *InstallationRef { return h.Installation } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *StatusHook) GetInstallationRef() *InstallationRef { return h.Installation } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *CheckRunHook) GetInstallationRef() *InstallationRef { return h.Installation } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *CheckSuiteHook) GetInstallationRef() *InstallationRef { return h.Installation } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *DeploymentStatusHook) GetInstallationRef() *InstallationRef { return h.Installation } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *ReleaseHook) GetInstallationRef() *InstallationRef { return h.Installation } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *RepositoryHook) GetInstallationRef() *InstallationRef { return h.Installation } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *ForkHook) GetInstallationRef() *InstallationRef { return h.Installation } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *WatchHook) GetInstallationRef() *InstallationRef { return h.Installation } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App +func (h *StarHook) GetInstallationRef() *InstallationRef { return nil } + +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App func (h *InstallationHook) GetInstallationRef() *InstallationRef { if h.Installation == nil { return nil @@ -425,6 +620,8 @@ func (h *InstallationHook) GetInstallationRef() *InstallationRef { } } +// GetInstallationRef returns the installation reference if the webhook is invoked on a +// GitHub App func (h *InstallationRepositoryHook) GetInstallationRef() *InstallationRef { if h.Installation == nil { return nil diff --git a/vendor/github.com/mitchellh/copystructure/.travis.yml b/vendor/github.com/mitchellh/copystructure/.travis.yml new file mode 100644 index 000000000..d7b9589ab --- /dev/null +++ b/vendor/github.com/mitchellh/copystructure/.travis.yml @@ -0,0 +1,12 @@ +language: go + +go: + - 1.7 + - tip + +script: + - go test + +matrix: + allow_failures: + - go: tip diff --git a/vendor/github.com/mitchellh/copystructure/LICENSE b/vendor/github.com/mitchellh/copystructure/LICENSE new file mode 100644 index 000000000..229851590 --- /dev/null +++ b/vendor/github.com/mitchellh/copystructure/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/copystructure/README.md b/vendor/github.com/mitchellh/copystructure/README.md new file mode 100644 index 000000000..bcb8c8d2c --- /dev/null +++ b/vendor/github.com/mitchellh/copystructure/README.md @@ -0,0 +1,21 @@ +# copystructure + +copystructure is a Go library for deep copying values in Go. + +This allows you to copy Go values that may contain reference values +such as maps, slices, or pointers, and copy their data as well instead +of just their references. + +## Installation + +Standard `go get`: + +``` +$ go get github.com/mitchellh/copystructure +``` + +## Usage & Example + +For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/copystructure). + +The `Copy` function has examples associated with it there. diff --git a/vendor/github.com/mitchellh/copystructure/copier_time.go b/vendor/github.com/mitchellh/copystructure/copier_time.go new file mode 100644 index 000000000..db6a6aa1a --- /dev/null +++ b/vendor/github.com/mitchellh/copystructure/copier_time.go @@ -0,0 +1,15 @@ +package copystructure + +import ( + "reflect" + "time" +) + +func init() { + Copiers[reflect.TypeOf(time.Time{})] = timeCopier +} + +func timeCopier(v interface{}) (interface{}, error) { + // Just... copy it. + return v.(time.Time), nil +} diff --git a/vendor/github.com/mitchellh/copystructure/copystructure.go b/vendor/github.com/mitchellh/copystructure/copystructure.go new file mode 100644 index 000000000..140435255 --- /dev/null +++ b/vendor/github.com/mitchellh/copystructure/copystructure.go @@ -0,0 +1,548 @@ +package copystructure + +import ( + "errors" + "reflect" + "sync" + + "github.com/mitchellh/reflectwalk" +) + +// Copy returns a deep copy of v. +func Copy(v interface{}) (interface{}, error) { + return Config{}.Copy(v) +} + +// CopierFunc is a function that knows how to deep copy a specific type. +// Register these globally with the Copiers variable. +type CopierFunc func(interface{}) (interface{}, error) + +// Copiers is a map of types that behave specially when they are copied. +// If a type is found in this map while deep copying, this function +// will be called to copy it instead of attempting to copy all fields. +// +// The key should be the type, obtained using: reflect.TypeOf(value with type). +// +// It is unsafe to write to this map after Copies have started. If you +// are writing to this map while also copying, wrap all modifications to +// this map as well as to Copy in a mutex. +var Copiers map[reflect.Type]CopierFunc = make(map[reflect.Type]CopierFunc) + +// Must is a helper that wraps a call to a function returning +// (interface{}, error) and panics if the error is non-nil. It is intended +// for use in variable initializations and should only be used when a copy +// error should be a crashing case. +func Must(v interface{}, err error) interface{} { + if err != nil { + panic("copy error: " + err.Error()) + } + + return v +} + +var errPointerRequired = errors.New("Copy argument must be a pointer when Lock is true") + +type Config struct { + // Lock any types that are a sync.Locker and are not a mutex while copying. + // If there is an RLocker method, use that to get the sync.Locker. + Lock bool + + // Copiers is a map of types associated with a CopierFunc. Use the global + // Copiers map if this is nil. + Copiers map[reflect.Type]CopierFunc +} + +func (c Config) Copy(v interface{}) (interface{}, error) { + if c.Lock && reflect.ValueOf(v).Kind() != reflect.Ptr { + return nil, errPointerRequired + } + + w := new(walker) + if c.Lock { + w.useLocks = true + } + + if c.Copiers == nil { + c.Copiers = Copiers + } + + err := reflectwalk.Walk(v, w) + if err != nil { + return nil, err + } + + // Get the result. If the result is nil, then we want to turn it + // into a typed nil if we can. + result := w.Result + if result == nil { + val := reflect.ValueOf(v) + result = reflect.Indirect(reflect.New(val.Type())).Interface() + } + + return result, nil +} + +// Return the key used to index interfaces types we've seen. Store the number +// of pointers in the upper 32bits, and the depth in the lower 32bits. This is +// easy to calculate, easy to match a key with our current depth, and we don't +// need to deal with initializing and cleaning up nested maps or slices. +func ifaceKey(pointers, depth int) uint64 { + return uint64(pointers)<<32 | uint64(depth) +} + +type walker struct { + Result interface{} + + depth int + ignoreDepth int + vals []reflect.Value + cs []reflect.Value + + // This stores the number of pointers we've walked over, indexed by depth. + ps []int + + // If an interface is indirected by a pointer, we need to know the type of + // interface to create when creating the new value. Store the interface + // types here, indexed by both the walk depth and the number of pointers + // already seen at that depth. Use ifaceKey to calculate the proper uint64 + // value. + ifaceTypes map[uint64]reflect.Type + + // any locks we've taken, indexed by depth + locks []sync.Locker + // take locks while walking the structure + useLocks bool +} + +func (w *walker) Enter(l reflectwalk.Location) error { + w.depth++ + + // ensure we have enough elements to index via w.depth + for w.depth >= len(w.locks) { + w.locks = append(w.locks, nil) + } + + for len(w.ps) < w.depth+1 { + w.ps = append(w.ps, 0) + } + + return nil +} + +func (w *walker) Exit(l reflectwalk.Location) error { + locker := w.locks[w.depth] + w.locks[w.depth] = nil + if locker != nil { + defer locker.Unlock() + } + + // clear out pointers and interfaces as we exit the stack + w.ps[w.depth] = 0 + + for k := range w.ifaceTypes { + mask := uint64(^uint32(0)) + if k&mask == uint64(w.depth) { + delete(w.ifaceTypes, k) + } + } + + w.depth-- + if w.ignoreDepth > w.depth { + w.ignoreDepth = 0 + } + + if w.ignoring() { + return nil + } + + switch l { + case reflectwalk.Array: + fallthrough + case reflectwalk.Map: + fallthrough + case reflectwalk.Slice: + w.replacePointerMaybe() + + // Pop map off our container + w.cs = w.cs[:len(w.cs)-1] + case reflectwalk.MapValue: + // Pop off the key and value + mv := w.valPop() + mk := w.valPop() + m := w.cs[len(w.cs)-1] + + // If mv is the zero value, SetMapIndex deletes the key form the map, + // or in this case never adds it. We need to create a properly typed + // zero value so that this key can be set. + if !mv.IsValid() { + mv = reflect.Zero(m.Elem().Type().Elem()) + } + m.Elem().SetMapIndex(mk, mv) + case reflectwalk.ArrayElem: + // Pop off the value and the index and set it on the array + v := w.valPop() + i := w.valPop().Interface().(int) + if v.IsValid() { + a := w.cs[len(w.cs)-1] + ae := a.Elem().Index(i) // storing array as pointer on stack - so need Elem() call + if ae.CanSet() { + ae.Set(v) + } + } + case reflectwalk.SliceElem: + // Pop off the value and the index and set it on the slice + v := w.valPop() + i := w.valPop().Interface().(int) + if v.IsValid() { + s := w.cs[len(w.cs)-1] + se := s.Elem().Index(i) + if se.CanSet() { + se.Set(v) + } + } + case reflectwalk.Struct: + w.replacePointerMaybe() + + // Remove the struct from the container stack + w.cs = w.cs[:len(w.cs)-1] + case reflectwalk.StructField: + // Pop off the value and the field + v := w.valPop() + f := w.valPop().Interface().(reflect.StructField) + if v.IsValid() { + s := w.cs[len(w.cs)-1] + sf := reflect.Indirect(s).FieldByName(f.Name) + + if sf.CanSet() { + sf.Set(v) + } + } + case reflectwalk.WalkLoc: + // Clear out the slices for GC + w.cs = nil + w.vals = nil + } + + return nil +} + +func (w *walker) Map(m reflect.Value) error { + if w.ignoring() { + return nil + } + w.lock(m) + + // Create the map. If the map itself is nil, then just make a nil map + var newMap reflect.Value + if m.IsNil() { + newMap = reflect.New(m.Type()) + } else { + newMap = wrapPtr(reflect.MakeMap(m.Type())) + } + + w.cs = append(w.cs, newMap) + w.valPush(newMap) + return nil +} + +func (w *walker) MapElem(m, k, v reflect.Value) error { + return nil +} + +func (w *walker) PointerEnter(v bool) error { + if v { + w.ps[w.depth]++ + } + return nil +} + +func (w *walker) PointerExit(v bool) error { + if v { + w.ps[w.depth]-- + } + return nil +} + +func (w *walker) Interface(v reflect.Value) error { + if !v.IsValid() { + return nil + } + if w.ifaceTypes == nil { + w.ifaceTypes = make(map[uint64]reflect.Type) + } + + w.ifaceTypes[ifaceKey(w.ps[w.depth], w.depth)] = v.Type() + return nil +} + +func (w *walker) Primitive(v reflect.Value) error { + if w.ignoring() { + return nil + } + w.lock(v) + + // IsValid verifies the v is non-zero and CanInterface verifies + // that we're allowed to read this value (unexported fields). + var newV reflect.Value + if v.IsValid() && v.CanInterface() { + newV = reflect.New(v.Type()) + newV.Elem().Set(v) + } + + w.valPush(newV) + w.replacePointerMaybe() + return nil +} + +func (w *walker) Slice(s reflect.Value) error { + if w.ignoring() { + return nil + } + w.lock(s) + + var newS reflect.Value + if s.IsNil() { + newS = reflect.New(s.Type()) + } else { + newS = wrapPtr(reflect.MakeSlice(s.Type(), s.Len(), s.Cap())) + } + + w.cs = append(w.cs, newS) + w.valPush(newS) + return nil +} + +func (w *walker) SliceElem(i int, elem reflect.Value) error { + if w.ignoring() { + return nil + } + + // We don't write the slice here because elem might still be + // arbitrarily complex. Just record the index and continue on. + w.valPush(reflect.ValueOf(i)) + + return nil +} + +func (w *walker) Array(a reflect.Value) error { + if w.ignoring() { + return nil + } + w.lock(a) + + newA := reflect.New(a.Type()) + + w.cs = append(w.cs, newA) + w.valPush(newA) + return nil +} + +func (w *walker) ArrayElem(i int, elem reflect.Value) error { + if w.ignoring() { + return nil + } + + // We don't write the array here because elem might still be + // arbitrarily complex. Just record the index and continue on. + w.valPush(reflect.ValueOf(i)) + + return nil +} + +func (w *walker) Struct(s reflect.Value) error { + if w.ignoring() { + return nil + } + w.lock(s) + + var v reflect.Value + if c, ok := Copiers[s.Type()]; ok { + // We have a Copier for this struct, so we use that copier to + // get the copy, and we ignore anything deeper than this. + w.ignoreDepth = w.depth + + dup, err := c(s.Interface()) + if err != nil { + return err + } + + // We need to put a pointer to the value on the value stack, + // so allocate a new pointer and set it. + v = reflect.New(s.Type()) + reflect.Indirect(v).Set(reflect.ValueOf(dup)) + } else { + // No copier, we copy ourselves and allow reflectwalk to guide + // us deeper into the structure for copying. + v = reflect.New(s.Type()) + } + + // Push the value onto the value stack for setting the struct field, + // and add the struct itself to the containers stack in case we walk + // deeper so that its own fields can be modified. + w.valPush(v) + w.cs = append(w.cs, v) + + return nil +} + +func (w *walker) StructField(f reflect.StructField, v reflect.Value) error { + if w.ignoring() { + return nil + } + + // If PkgPath is non-empty, this is a private (unexported) field. + // We do not set this unexported since the Go runtime doesn't allow us. + if f.PkgPath != "" { + return reflectwalk.SkipEntry + } + + // Push the field onto the stack, we'll handle it when we exit + // the struct field in Exit... + w.valPush(reflect.ValueOf(f)) + return nil +} + +// ignore causes the walker to ignore any more values until we exit this on +func (w *walker) ignore() { + w.ignoreDepth = w.depth +} + +func (w *walker) ignoring() bool { + return w.ignoreDepth > 0 && w.depth >= w.ignoreDepth +} + +func (w *walker) pointerPeek() bool { + return w.ps[w.depth] > 0 +} + +func (w *walker) valPop() reflect.Value { + result := w.vals[len(w.vals)-1] + w.vals = w.vals[:len(w.vals)-1] + + // If we're out of values, that means we popped everything off. In + // this case, we reset the result so the next pushed value becomes + // the result. + if len(w.vals) == 0 { + w.Result = nil + } + + return result +} + +func (w *walker) valPush(v reflect.Value) { + w.vals = append(w.vals, v) + + // If we haven't set the result yet, then this is the result since + // it is the first (outermost) value we're seeing. + if w.Result == nil && v.IsValid() { + w.Result = v.Interface() + } +} + +func (w *walker) replacePointerMaybe() { + // Determine the last pointer value. If it is NOT a pointer, then + // we need to push that onto the stack. + if !w.pointerPeek() { + w.valPush(reflect.Indirect(w.valPop())) + return + } + + v := w.valPop() + + // If the expected type is a pointer to an interface of any depth, + // such as *interface{}, **interface{}, etc., then we need to convert + // the value "v" from *CONCRETE to *interface{} so types match for + // Set. + // + // Example if v is type *Foo where Foo is a struct, v would become + // *interface{} instead. This only happens if we have an interface expectation + // at this depth. + // + // For more info, see GH-16 + if iType, ok := w.ifaceTypes[ifaceKey(w.ps[w.depth], w.depth)]; ok && iType.Kind() == reflect.Interface { + y := reflect.New(iType) // Create *interface{} + y.Elem().Set(reflect.Indirect(v)) // Assign "Foo" to interface{} (dereferenced) + v = y // v is now typed *interface{} (where *v = Foo) + } + + for i := 1; i < w.ps[w.depth]; i++ { + if iType, ok := w.ifaceTypes[ifaceKey(w.ps[w.depth]-i, w.depth)]; ok { + iface := reflect.New(iType).Elem() + iface.Set(v) + v = iface + } + + p := reflect.New(v.Type()) + p.Elem().Set(v) + v = p + } + + w.valPush(v) +} + +// if this value is a Locker, lock it and add it to the locks slice +func (w *walker) lock(v reflect.Value) { + if !w.useLocks { + return + } + + if !v.IsValid() || !v.CanInterface() { + return + } + + type rlocker interface { + RLocker() sync.Locker + } + + var locker sync.Locker + + // We can't call Interface() on a value directly, since that requires + // a copy. This is OK, since the pointer to a value which is a sync.Locker + // is also a sync.Locker. + if v.Kind() == reflect.Ptr { + switch l := v.Interface().(type) { + case rlocker: + // don't lock a mutex directly + if _, ok := l.(*sync.RWMutex); !ok { + locker = l.RLocker() + } + case sync.Locker: + locker = l + } + } else if v.CanAddr() { + switch l := v.Addr().Interface().(type) { + case rlocker: + // don't lock a mutex directly + if _, ok := l.(*sync.RWMutex); !ok { + locker = l.RLocker() + } + case sync.Locker: + locker = l + } + } + + // still no callable locker + if locker == nil { + return + } + + // don't lock a mutex directly + switch locker.(type) { + case *sync.Mutex, *sync.RWMutex: + return + } + + locker.Lock() + w.locks[w.depth] = locker +} + +// wrapPtr is a helper that takes v and always make it *v. copystructure +// stores things internally as pointers until the last moment before unwrapping +func wrapPtr(v reflect.Value) reflect.Value { + if !v.IsValid() { + return v + } + vPtr := reflect.New(v.Type()) + vPtr.Elem().Set(v) + return vPtr +} diff --git a/vendor/github.com/mitchellh/copystructure/go.mod b/vendor/github.com/mitchellh/copystructure/go.mod new file mode 100644 index 000000000..d01864309 --- /dev/null +++ b/vendor/github.com/mitchellh/copystructure/go.mod @@ -0,0 +1,3 @@ +module github.com/mitchellh/copystructure + +require github.com/mitchellh/reflectwalk v1.0.0 diff --git a/vendor/github.com/mitchellh/copystructure/go.sum b/vendor/github.com/mitchellh/copystructure/go.sum new file mode 100644 index 000000000..be5724561 --- /dev/null +++ b/vendor/github.com/mitchellh/copystructure/go.sum @@ -0,0 +1,2 @@ +github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= diff --git a/vendor/github.com/mitchellh/reflectwalk/.travis.yml b/vendor/github.com/mitchellh/reflectwalk/.travis.yml new file mode 100644 index 000000000..4f2ee4d97 --- /dev/null +++ b/vendor/github.com/mitchellh/reflectwalk/.travis.yml @@ -0,0 +1 @@ +language: go diff --git a/vendor/github.com/mitchellh/reflectwalk/LICENSE b/vendor/github.com/mitchellh/reflectwalk/LICENSE new file mode 100644 index 000000000..f9c841a51 --- /dev/null +++ b/vendor/github.com/mitchellh/reflectwalk/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/reflectwalk/README.md b/vendor/github.com/mitchellh/reflectwalk/README.md new file mode 100644 index 000000000..ac82cd2e1 --- /dev/null +++ b/vendor/github.com/mitchellh/reflectwalk/README.md @@ -0,0 +1,6 @@ +# reflectwalk + +reflectwalk is a Go library for "walking" a value in Go using reflection, +in the same way a directory tree can be "walked" on the filesystem. Walking +a complex structure can allow you to do manipulations on unknown structures +such as those decoded from JSON. diff --git a/vendor/github.com/mitchellh/reflectwalk/go.mod b/vendor/github.com/mitchellh/reflectwalk/go.mod new file mode 100644 index 000000000..52bb7c469 --- /dev/null +++ b/vendor/github.com/mitchellh/reflectwalk/go.mod @@ -0,0 +1 @@ +module github.com/mitchellh/reflectwalk diff --git a/vendor/github.com/mitchellh/reflectwalk/location.go b/vendor/github.com/mitchellh/reflectwalk/location.go new file mode 100644 index 000000000..6a7f17611 --- /dev/null +++ b/vendor/github.com/mitchellh/reflectwalk/location.go @@ -0,0 +1,19 @@ +package reflectwalk + +//go:generate stringer -type=Location location.go + +type Location uint + +const ( + None Location = iota + Map + MapKey + MapValue + Slice + SliceElem + Array + ArrayElem + Struct + StructField + WalkLoc +) diff --git a/vendor/github.com/mitchellh/reflectwalk/location_string.go b/vendor/github.com/mitchellh/reflectwalk/location_string.go new file mode 100644 index 000000000..70760cf4c --- /dev/null +++ b/vendor/github.com/mitchellh/reflectwalk/location_string.go @@ -0,0 +1,16 @@ +// Code generated by "stringer -type=Location location.go"; DO NOT EDIT. + +package reflectwalk + +import "fmt" + +const _Location_name = "NoneMapMapKeyMapValueSliceSliceElemArrayArrayElemStructStructFieldWalkLoc" + +var _Location_index = [...]uint8{0, 4, 7, 13, 21, 26, 35, 40, 49, 55, 66, 73} + +func (i Location) String() string { + if i >= Location(len(_Location_index)-1) { + return fmt.Sprintf("Location(%d)", i) + } + return _Location_name[_Location_index[i]:_Location_index[i+1]] +} diff --git a/vendor/github.com/mitchellh/reflectwalk/reflectwalk.go b/vendor/github.com/mitchellh/reflectwalk/reflectwalk.go new file mode 100644 index 000000000..d7ab7b6d7 --- /dev/null +++ b/vendor/github.com/mitchellh/reflectwalk/reflectwalk.go @@ -0,0 +1,401 @@ +// reflectwalk is a package that allows you to "walk" complex structures +// similar to how you may "walk" a filesystem: visiting every element one +// by one and calling callback functions allowing you to handle and manipulate +// those elements. +package reflectwalk + +import ( + "errors" + "reflect" +) + +// PrimitiveWalker implementations are able to handle primitive values +// within complex structures. Primitive values are numbers, strings, +// booleans, funcs, chans. +// +// These primitive values are often members of more complex +// structures (slices, maps, etc.) that are walkable by other interfaces. +type PrimitiveWalker interface { + Primitive(reflect.Value) error +} + +// InterfaceWalker implementations are able to handle interface values as they +// are encountered during the walk. +type InterfaceWalker interface { + Interface(reflect.Value) error +} + +// MapWalker implementations are able to handle individual elements +// found within a map structure. +type MapWalker interface { + Map(m reflect.Value) error + MapElem(m, k, v reflect.Value) error +} + +// SliceWalker implementations are able to handle slice elements found +// within complex structures. +type SliceWalker interface { + Slice(reflect.Value) error + SliceElem(int, reflect.Value) error +} + +// ArrayWalker implementations are able to handle array elements found +// within complex structures. +type ArrayWalker interface { + Array(reflect.Value) error + ArrayElem(int, reflect.Value) error +} + +// StructWalker is an interface that has methods that are called for +// structs when a Walk is done. +type StructWalker interface { + Struct(reflect.Value) error + StructField(reflect.StructField, reflect.Value) error +} + +// EnterExitWalker implementations are notified before and after +// they walk deeper into complex structures (into struct fields, +// into slice elements, etc.) +type EnterExitWalker interface { + Enter(Location) error + Exit(Location) error +} + +// PointerWalker implementations are notified when the value they're +// walking is a pointer or not. Pointer is called for _every_ value whether +// it is a pointer or not. +type PointerWalker interface { + PointerEnter(bool) error + PointerExit(bool) error +} + +// SkipEntry can be returned from walk functions to skip walking +// the value of this field. This is only valid in the following functions: +// +// - Struct: skips all fields from being walked +// - StructField: skips walking the struct value +// +var SkipEntry = errors.New("skip this entry") + +// Walk takes an arbitrary value and an interface and traverses the +// value, calling callbacks on the interface if they are supported. +// The interface should implement one or more of the walker interfaces +// in this package, such as PrimitiveWalker, StructWalker, etc. +func Walk(data, walker interface{}) (err error) { + v := reflect.ValueOf(data) + ew, ok := walker.(EnterExitWalker) + if ok { + err = ew.Enter(WalkLoc) + } + + if err == nil { + err = walk(v, walker) + } + + if ok && err == nil { + err = ew.Exit(WalkLoc) + } + + return +} + +func walk(v reflect.Value, w interface{}) (err error) { + // Determine if we're receiving a pointer and if so notify the walker. + // The logic here is convoluted but very important (tests will fail if + // almost any part is changed). I will try to explain here. + // + // First, we check if the value is an interface, if so, we really need + // to check the interface's VALUE to see whether it is a pointer. + // + // Check whether the value is then a pointer. If so, then set pointer + // to true to notify the user. + // + // If we still have a pointer or an interface after the indirections, then + // we unwrap another level + // + // At this time, we also set "v" to be the dereferenced value. This is + // because once we've unwrapped the pointer we want to use that value. + pointer := false + pointerV := v + + for { + if pointerV.Kind() == reflect.Interface { + if iw, ok := w.(InterfaceWalker); ok { + if err = iw.Interface(pointerV); err != nil { + return + } + } + + pointerV = pointerV.Elem() + } + + if pointerV.Kind() == reflect.Ptr { + pointer = true + v = reflect.Indirect(pointerV) + } + if pw, ok := w.(PointerWalker); ok { + if err = pw.PointerEnter(pointer); err != nil { + return + } + + defer func(pointer bool) { + if err != nil { + return + } + + err = pw.PointerExit(pointer) + }(pointer) + } + + if pointer { + pointerV = v + } + pointer = false + + // If we still have a pointer or interface we have to indirect another level. + switch pointerV.Kind() { + case reflect.Ptr, reflect.Interface: + continue + } + break + } + + // We preserve the original value here because if it is an interface + // type, we want to pass that directly into the walkPrimitive, so that + // we can set it. + originalV := v + if v.Kind() == reflect.Interface { + v = v.Elem() + } + + k := v.Kind() + if k >= reflect.Int && k <= reflect.Complex128 { + k = reflect.Int + } + + switch k { + // Primitives + case reflect.Bool, reflect.Chan, reflect.Func, reflect.Int, reflect.String, reflect.Invalid: + err = walkPrimitive(originalV, w) + return + case reflect.Map: + err = walkMap(v, w) + return + case reflect.Slice: + err = walkSlice(v, w) + return + case reflect.Struct: + err = walkStruct(v, w) + return + case reflect.Array: + err = walkArray(v, w) + return + default: + panic("unsupported type: " + k.String()) + } +} + +func walkMap(v reflect.Value, w interface{}) error { + ew, ewok := w.(EnterExitWalker) + if ewok { + ew.Enter(Map) + } + + if mw, ok := w.(MapWalker); ok { + if err := mw.Map(v); err != nil { + return err + } + } + + for _, k := range v.MapKeys() { + kv := v.MapIndex(k) + + if mw, ok := w.(MapWalker); ok { + if err := mw.MapElem(v, k, kv); err != nil { + return err + } + } + + ew, ok := w.(EnterExitWalker) + if ok { + ew.Enter(MapKey) + } + + if err := walk(k, w); err != nil { + return err + } + + if ok { + ew.Exit(MapKey) + ew.Enter(MapValue) + } + + if err := walk(kv, w); err != nil { + return err + } + + if ok { + ew.Exit(MapValue) + } + } + + if ewok { + ew.Exit(Map) + } + + return nil +} + +func walkPrimitive(v reflect.Value, w interface{}) error { + if pw, ok := w.(PrimitiveWalker); ok { + return pw.Primitive(v) + } + + return nil +} + +func walkSlice(v reflect.Value, w interface{}) (err error) { + ew, ok := w.(EnterExitWalker) + if ok { + ew.Enter(Slice) + } + + if sw, ok := w.(SliceWalker); ok { + if err := sw.Slice(v); err != nil { + return err + } + } + + for i := 0; i < v.Len(); i++ { + elem := v.Index(i) + + if sw, ok := w.(SliceWalker); ok { + if err := sw.SliceElem(i, elem); err != nil { + return err + } + } + + ew, ok := w.(EnterExitWalker) + if ok { + ew.Enter(SliceElem) + } + + if err := walk(elem, w); err != nil { + return err + } + + if ok { + ew.Exit(SliceElem) + } + } + + ew, ok = w.(EnterExitWalker) + if ok { + ew.Exit(Slice) + } + + return nil +} + +func walkArray(v reflect.Value, w interface{}) (err error) { + ew, ok := w.(EnterExitWalker) + if ok { + ew.Enter(Array) + } + + if aw, ok := w.(ArrayWalker); ok { + if err := aw.Array(v); err != nil { + return err + } + } + + for i := 0; i < v.Len(); i++ { + elem := v.Index(i) + + if aw, ok := w.(ArrayWalker); ok { + if err := aw.ArrayElem(i, elem); err != nil { + return err + } + } + + ew, ok := w.(EnterExitWalker) + if ok { + ew.Enter(ArrayElem) + } + + if err := walk(elem, w); err != nil { + return err + } + + if ok { + ew.Exit(ArrayElem) + } + } + + ew, ok = w.(EnterExitWalker) + if ok { + ew.Exit(Array) + } + + return nil +} + +func walkStruct(v reflect.Value, w interface{}) (err error) { + ew, ewok := w.(EnterExitWalker) + if ewok { + ew.Enter(Struct) + } + + skip := false + if sw, ok := w.(StructWalker); ok { + err = sw.Struct(v) + if err == SkipEntry { + skip = true + err = nil + } + if err != nil { + return + } + } + + if !skip { + vt := v.Type() + for i := 0; i < vt.NumField(); i++ { + sf := vt.Field(i) + f := v.FieldByIndex([]int{i}) + + if sw, ok := w.(StructWalker); ok { + err = sw.StructField(sf, f) + + // SkipEntry just pretends this field doesn't even exist + if err == SkipEntry { + continue + } + + if err != nil { + return + } + } + + ew, ok := w.(EnterExitWalker) + if ok { + ew.Enter(StructField) + } + + err = walk(f, w) + if err != nil { + return + } + + if ok { + ew.Exit(StructField) + } + } + } + + if ewok { + ew.Exit(Struct) + } + + return nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index d28d01896..1a5a4e5bf 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,4 +1,4 @@ -# code.gitea.io/sdk/gitea v0.12.1 +# code.gitea.io/sdk/gitea v0.13.1-0.20210217150345-a968e32ca15c code.gitea.io/sdk/gitea # github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 github.com/Azure/go-ansiterm @@ -127,7 +127,7 @@ github.com/googleapis/gnostic/extensions github.com/h2non/gock # github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 github.com/h2non/parth -# github.com/hashicorp/go-version v1.2.0 +# github.com/hashicorp/go-version v1.2.1 github.com/hashicorp/go-version # github.com/hashicorp/golang-lru v0.5.4 github.com/hashicorp/golang-lru @@ -138,7 +138,7 @@ github.com/hashicorp/golang-lru/simplelru github.com/imdario/mergo # github.com/inconshreveable/mousetrap v1.0.0 github.com/inconshreveable/mousetrap -# github.com/jenkins-x/go-scm v1.5.160 +# github.com/jenkins-x/go-scm v1.6.6 ## explicit github.com/jenkins-x/go-scm/pkg/hmac github.com/jenkins-x/go-scm/scm @@ -151,6 +151,7 @@ github.com/jenkins-x/go-scm/scm/driver/gogs github.com/jenkins-x/go-scm/scm/driver/internal/null github.com/jenkins-x/go-scm/scm/driver/stash github.com/jenkins-x/go-scm/scm/factory +github.com/jenkins-x/go-scm/scm/labels github.com/jenkins-x/go-scm/scm/transport # github.com/json-iterator/go v1.1.9 github.com/json-iterator/go @@ -169,11 +170,15 @@ github.com/mattn/go-isatty # github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d ## explicit github.com/mgutz/ansi +# github.com/mitchellh/copystructure v1.0.0 +github.com/mitchellh/copystructure # github.com/mitchellh/go-homedir v1.1.0 ## explicit github.com/mitchellh/go-homedir # github.com/mitchellh/go-wordwrap v1.0.0 github.com/mitchellh/go-wordwrap +# github.com/mitchellh/reflectwalk v1.0.0 +github.com/mitchellh/reflectwalk # github.com/mkmik/multierror v0.3.0 ## explicit github.com/mkmik/multierror