summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
author6543 <6543@obermui.de>2021-01-21 20:33:58 +0100
committerGitHub <noreply@github.com>2021-01-21 20:33:58 +0100
commit81c833d92d04e0a5579e7168aba548dad7e17451 (patch)
treec928f1b43fc6e2f27603193f0eed657f0760c96d
parentb5570d3e680570343c1552bfc972b19b161209cd (diff)
downloadgitea-81c833d92d04e0a5579e7168aba548dad7e17451.tar.gz
gitea-81c833d92d04e0a5579e7168aba548dad7e17451.zip
Add support to migrate from gogs (#14342)
Add support to migrate gogs: * issues * comments * labels * milestones * wiki Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: Andrew Thornton <art27@cantab.net>
-rw-r--r--go.mod3
-rw-r--r--go.sum59
-rw-r--r--modules/migrations/base/downloader.go212
-rw-r--r--modules/migrations/base/error.go26
-rw-r--r--modules/migrations/base/milestone.go2
-rw-r--r--modules/migrations/base/null_downloader.go82
-rw-r--r--modules/migrations/base/retry_downloader.go247
-rw-r--r--modules/migrations/error.go3
-rw-r--r--modules/migrations/git.go40
-rw-r--r--modules/migrations/gitea_downloader.go3
-rw-r--r--modules/migrations/gitea_uploader.go23
-rw-r--r--modules/migrations/github.go1
-rw-r--r--modules/migrations/gitlab.go1
-rw-r--r--modules/migrations/gogs.go312
-rw-r--r--modules/migrations/gogs_test.go122
-rw-r--r--modules/migrations/migrate.go83
-rw-r--r--modules/migrations/restore.go1
-rw-r--r--modules/structs/repo.go1
-rw-r--r--options/locale/locale_en-US.ini1
-rw-r--r--public/img/svg/gitea-gogs.svg1
-rw-r--r--routers/api/v1/repo/migrate.go3
-rw-r--r--templates/repo/migrate/gogs.tmpl139
-rw-r--r--vendor/github.com/gogs/go-gogs-client/.gitignore25
-rw-r--r--vendor/github.com/gogs/go-gogs-client/LICENSE22
-rw-r--r--vendor/github.com/gogs/go-gogs-client/README.md8
-rw-r--r--vendor/github.com/gogs/go-gogs-client/admin_org.go43
-rw-r--r--vendor/github.com/gogs/go-gogs-client/admin_repo.go21
-rw-r--r--vendor/github.com/gogs/go-gogs-client/admin_user.go68
-rw-r--r--vendor/github.com/gogs/go-gogs-client/gogs.go90
-rw-r--r--vendor/github.com/gogs/go-gogs-client/issue.go103
-rw-r--r--vendor/github.com/gogs/go-gogs-client/issue_comment.go70
-rw-r--r--vendor/github.com/gogs/go-gogs-client/issue_label.go99
-rw-r--r--vendor/github.com/gogs/go-gogs-client/issue_milestone.go69
-rw-r--r--vendor/github.com/gogs/go-gogs-client/media_types.go9
-rw-r--r--vendor/github.com/gogs/go-gogs-client/miscellaneous.go10
-rw-r--r--vendor/github.com/gogs/go-gogs-client/org.go69
-rw-r--r--vendor/github.com/gogs/go-gogs-client/org_member.go24
-rw-r--r--vendor/github.com/gogs/go-gogs-client/org_team.go25
-rw-r--r--vendor/github.com/gogs/go-gogs-client/pull.go37
-rw-r--r--vendor/github.com/gogs/go-gogs-client/release.go22
-rw-r--r--vendor/github.com/gogs/go-gogs-client/repo.go172
-rw-r--r--vendor/github.com/gogs/go-gogs-client/repo_branch.go25
-rw-r--r--vendor/github.com/gogs/go-gogs-client/repo_collaborator.go44
-rw-r--r--vendor/github.com/gogs/go-gogs-client/repo_commit.go53
-rw-r--r--vendor/github.com/gogs/go-gogs-client/repo_file.go23
-rw-r--r--vendor/github.com/gogs/go-gogs-client/repo_hook.go345
-rw-r--r--vendor/github.com/gogs/go-gogs-client/repo_key.go50
-rw-r--r--vendor/github.com/gogs/go-gogs-client/user.go31
-rw-r--r--vendor/github.com/gogs/go-gogs-client/user_app.go46
-rw-r--r--vendor/github.com/gogs/go-gogs-client/user_email.go43
-rw-r--r--vendor/github.com/gogs/go-gogs-client/user_follow.go47
-rw-r--r--vendor/github.com/gogs/go-gogs-client/user_key.go49
-rw-r--r--vendor/github.com/gogs/go-gogs-client/utils.go23
-rw-r--r--vendor/modules.txt4
-rw-r--r--web_src/svg/gitea-gogs.svg1
55 files changed, 2782 insertions, 353 deletions
diff --git a/go.mod b/go.mod
index 3c491d0dbe..dd395465f7 100644
--- a/go.mod
+++ b/go.mod
@@ -46,6 +46,7 @@ require (
github.com/gobwas/glob v0.2.3
github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
+ github.com/gogs/go-gogs-client v0.0.0-20200905025246-8bb8a50cb355
github.com/google/go-github/v32 v32.1.0
github.com/google/uuid v1.1.2
github.com/gorilla/context v1.1.1
@@ -128,3 +129,5 @@ require (
replace github.com/hashicorp/go-version => github.com/6543/go-version v1.2.4
replace github.com/microcosm-cc/bluemonday => github.com/lunny/bluemonday v1.0.5-0.20201227154428-ca34796141e8
+
+replace github.com/gogs/go-gogs-client => github.com/6543-forks/go-gogs-client v0.0.0-20210116182316-f2f8bc0ea9cc
diff --git a/go.sum b/go.sum
index 32aa7588e5..ac15f52b6a 100644
--- a/go.sum
+++ b/go.sum
@@ -80,6 +80,8 @@ gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7 h1:N9QFoeNsUXLhl14m
gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7/go.mod h1:kgsbFPPS4P+acDYDOPDa3N4IWWOuDJt5/INKRUz7aks=
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
+github.com/6543-forks/go-gogs-client v0.0.0-20210116182316-f2f8bc0ea9cc h1:FLylYVXDwK+YtrmXYnv2Q1Y5lQ9TU1Xp5F2vndIOTb4=
+github.com/6543-forks/go-gogs-client v0.0.0-20210116182316-f2f8bc0ea9cc/go.mod h1:1Jj2LLcHcL+RHIT1IOaEsnoawRw+sjZYoiAjFWKJN/o=
github.com/6543/go-version v1.2.4 h1:MPsSnqNrM0HwA9tnmWNnsMdQMg4/u4fflARjwomoof4=
github.com/6543/go-version v1.2.4/go.mod h1:oqFAHCwtLVUTLdhQmVZWYvaHXTdsbB4SY85at64SQEo=
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28=
@@ -466,6 +468,8 @@ github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
+github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28 h1:gBeyun7mySAKWg7Fb0GOcv0upX9bdaZScs8QcRo8mEY=
github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
@@ -498,12 +502,10 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
-github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw=
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@@ -514,10 +516,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
@@ -539,7 +539,6 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200905233945-acf8798be1f7/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -604,13 +603,11 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
-github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
-github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
@@ -671,7 +668,6 @@ github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGAR
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
-github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -710,7 +706,6 @@ github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgo
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s=
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
-github.com/klauspost/pgzip v1.2.4 h1:TQ7CNpYKovDOmqzRHKxJh0BeaBI7UdQZYc6p7pMQh1A=
github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
@@ -745,9 +740,7 @@ github.com/lunny/bluemonday v1.0.5-0.20201227154428-ca34796141e8 h1:1omo92DLtxQu
github.com/lunny/bluemonday v1.0.5-0.20201227154428-ca34796141e8/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w=
github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96 h1:uNwtsDp7ci48vBTTxDuwcoTXz4lwtDTe7TjCQ0noaWY=
github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96/go.mod h1:mmIfjCSQlGYXmJ95jFN84AkQFnVABtKuJL8IrzwvUKQ=
-github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de h1:nyxwRdWHAVxpFcDThedEgQ07DbcRc5xgNObtbTp76fk=
github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de/go.mod h1:3q8WtuPQsoRbatJuy3nvq/hRSvuBJrHHr+ybPPiNvHQ=
-github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af h1:UaWHNBdukWrSG3DRvHFR/hyfg681fceqQDYVTBncKfQ=
github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af/go.mod h1:Cqz6pqow14VObJ7peltM+2n3PWOz7yTrfUuGbVFkzN0=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@@ -757,7 +750,6 @@ github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
-github.com/mailru/easyjson v0.7.1 h1:mdxE1MF9o53iCb2Ghj1VfWvh7ZOwHpnVG/xwXrV90U8=
github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
@@ -789,7 +781,6 @@ github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/Qd
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
-github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA=
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
github.com/mattn/go-sqlite3 v1.14.4 h1:4rQjbDxdu9fSgI/r3KN72G3c2goxknAqHHgPWWs8UlI=
github.com/mattn/go-sqlite3 v1.14.4/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
@@ -866,17 +857,14 @@ github.com/olivere/elastic/v7 v7.0.21/go.mod h1:Kh7iIsXIBl5qRQOBFoylCsXVTtye3keQ
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M=
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
-github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
-github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA=
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
@@ -899,14 +887,12 @@ github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bA
github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
-github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ=
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
-github.com/pierrec/lz4/v4 v4.0.3 h1:vNQKSVZNYUEAvRY9FaUXAF1XPbSOHJtDTiP41kzDz2E=
github.com/pierrec/lz4/v4 v4.0.3/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pierrec/lz4/v4 v4.1.1 h1:cS6aGkNLJr4u+UwaA21yp+gbWN3WJWtKo1axmPDObMA=
github.com/pierrec/lz4/v4 v4.1.1/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
@@ -933,7 +919,6 @@ github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
@@ -1000,7 +985,6 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
-github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w=
github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
github.com/smartystreets/assertions v1.1.1 h1:T/YLemO5Yp7KPzS+lVtu+WsHn8yoSwTfItdAd1r3cck=
github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
@@ -1030,7 +1014,6 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
-github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
@@ -1048,7 +1031,6 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -1058,7 +1040,6 @@ github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFd
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
-github.com/tinylib/msgp v1.1.0 h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU=
github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/tinylib/msgp v1.1.5 h1:2gXmtWueD2HefZHQe1QOy9HVzmFrLOVvsXwXBQ0ayy0=
github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg=
@@ -1070,7 +1051,6 @@ github.com/tstranex/u2f v1.0.0 h1:HhJkSzDDlVSVIVt7pDJwCHQj67k7A5EeBgPmeD+pVsQ=
github.com/tstranex/u2f v1.0.0/go.mod h1:eahSLaqAS0zsIEv80+vXT7WanXs7MQQDg3j3wGBSayo=
github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
-github.com/ulikunitz/xz v0.5.6 h1:jGHAfXawEGZQ3blwU5wnWKQJvAraT7Ftq9EXjnXYgt8=
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ=
@@ -1091,7 +1071,6 @@ github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU=
github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
-github.com/willf/bitset v1.1.10 h1:NotGKqX0KwQ72NUzqrjZq5ipPNDQex9lo3WpaS8L2sc=
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/willf/bitset v1.1.11 h1:N7Z7E9UvjW+sGsEl7k/SJrvY2reP1A07MrGuCjIOjRE=
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
@@ -1174,9 +1153,7 @@ golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620 h1:3wPMTskHO3+O6jqTEXyFcsnuxMQOqYSaHsDxcbUXpqA=
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
@@ -1255,8 +1232,6 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200927032502-5d4f70055728/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/net v0.0.0-20200930145003-4acb6c075d10 h1:YfxMZzv3PjGonQYNUaeU2+DhAdqOxerQ30JFB6WgAXo=
-golang.org/x/net v0.0.0-20200930145003-4acb6c075d10/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200930145003-4acb6c075d10/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
@@ -1267,7 +1242,6 @@ golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAG
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 h1:ld7aEMNHoBnnDAX15v1T6z31v8HwR2A9FYOuAhWqkwc=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
@@ -1318,10 +1292,8 @@ golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1338,16 +1310,11 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88=
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78 h1:nVuTkr9L6Bq62qpUqKo/RnZCFfzDBL0bYo6w9OJUqZY=
golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1357,7 +1324,6 @@ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fq
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
-golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -1406,7 +1372,6 @@ golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
@@ -1417,29 +1382,18 @@ golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
-golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
-golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
-golang.org/x/tools v0.0.0-20200921210052-fa0125251cc4 h1:v8Jgq9X6Es9K9otVr9jxENEJigepKMZgA9OmrIZDtFA=
golang.org/x/tools v0.0.0-20200921210052-fa0125251cc4/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20200928182047-19e03678916f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
-golang.org/x/tools v0.0.0-20200929161345-d7fc70abf50f h1:18s2P7JILnVhIF2+ZtGJQ9czV5bvTsb13/UGtNPDbjA=
golang.org/x/tools v0.0.0-20200929161345-d7fc70abf50f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9 h1:sEvmEcJVKBNUvgCUClbUQeHOAa9U0I2Ce1BooMvVCY4=
golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
@@ -1477,7 +1431,6 @@ google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.4/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
@@ -1554,7 +1507,6 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8X
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
-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.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
@@ -1598,10 +1550,7 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
mvdan.cc/xurls/v2 v2.2.0 h1:NSZPykBXJFCetGZykLAxaL6SIpvbVy/UFEniIfHAa8A=
mvdan.cc/xurls/v2 v2.2.0/go.mod h1:EV1RMtya9D6G5DMYPGD8zTQzaHet6Jh8gFlRgGRJeO8=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
-rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
-rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
-rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
diff --git a/modules/migrations/base/downloader.go b/modules/migrations/base/downloader.go
index afa99105c9..919f4b52a0 100644
--- a/modules/migrations/base/downloader.go
+++ b/modules/migrations/base/downloader.go
@@ -7,7 +7,6 @@ package base
import (
"context"
- "time"
"code.gitea.io/gitea/modules/structs"
)
@@ -24,6 +23,7 @@ type Downloader interface {
GetComments(issueNumber int64) ([]*Comment, error)
GetPullRequests(page, perPage int) ([]*PullRequest, bool, error)
GetReviews(pullRequestNumber int64) ([]*Review, error)
+ FormatCloneURL(opts MigrateOptions, remoteAddr string) (string, error)
}
// DownloaderFactory defines an interface to match a downloader implementation and create a downloader
@@ -31,213 +31,3 @@ type DownloaderFactory interface {
New(ctx context.Context, opts MigrateOptions) (Downloader, error)
GitServiceType() structs.GitServiceType
}
-
-var (
- _ Downloader = &RetryDownloader{}
-)
-
-// RetryDownloader retry the downloads
-type RetryDownloader struct {
- Downloader
- ctx context.Context
- RetryTimes int // the total execute times
- RetryDelay int // time to delay seconds
-}
-
-// NewRetryDownloader creates a retry downloader
-func NewRetryDownloader(ctx context.Context, downloader Downloader, retryTimes, retryDelay int) *RetryDownloader {
- return &RetryDownloader{
- Downloader: downloader,
- ctx: ctx,
- RetryTimes: retryTimes,
- RetryDelay: retryDelay,
- }
-}
-
-// SetContext set context
-func (d *RetryDownloader) SetContext(ctx context.Context) {
- d.ctx = ctx
- d.Downloader.SetContext(ctx)
-}
-
-// GetRepoInfo returns a repository information with retry
-func (d *RetryDownloader) GetRepoInfo() (*Repository, error) {
- var (
- times = d.RetryTimes
- repo *Repository
- err error
- )
- for ; times > 0; times-- {
- if repo, err = d.Downloader.GetRepoInfo(); err == nil {
- return repo, nil
- }
- select {
- case <-d.ctx.Done():
- return nil, d.ctx.Err()
- case <-time.After(time.Second * time.Duration(d.RetryDelay)):
- }
- }
- return nil, err
-}
-
-// GetTopics returns a repository's topics with retry
-func (d *RetryDownloader) GetTopics() ([]string, error) {
- var (
- times = d.RetryTimes
- topics []string
- err error
- )
- for ; times > 0; times-- {
- if topics, err = d.Downloader.GetTopics(); err == nil {
- return topics, nil
- }
- select {
- case <-d.ctx.Done():
- return nil, d.ctx.Err()
- case <-time.After(time.Second * time.Duration(d.RetryDelay)):
- }
- }
- return nil, err
-}
-
-// GetMilestones returns a repository's milestones with retry
-func (d *RetryDownloader) GetMilestones() ([]*Milestone, error) {
- var (
- times = d.RetryTimes
- milestones []*Milestone
- err error
- )
- for ; times > 0; times-- {
- if milestones, err = d.Downloader.GetMilestones(); err == nil {
- return milestones, nil
- }
- select {
- case <-d.ctx.Done():
- return nil, d.ctx.Err()
- case <-time.After(time.Second * time.Duration(d.RetryDelay)):
- }
- }
- return nil, err
-}
-
-// GetReleases returns a repository's releases with retry
-func (d *RetryDownloader) GetReleases() ([]*Release, error) {
- var (
- times = d.RetryTimes
- releases []*Release
- err error
- )
- for ; times > 0; times-- {
- if releases, err = d.Downloader.GetReleases(); err == nil {
- return releases, nil
- }
- select {
- case <-d.ctx.Done():
- return nil, d.ctx.Err()
- case <-time.After(time.Second * time.Duration(d.RetryDelay)):
- }
- }
- return nil, err
-}
-
-// GetLabels returns a repository's labels with retry
-func (d *RetryDownloader) GetLabels() ([]*Label, error) {
- var (
- times = d.RetryTimes
- labels []*Label
- err error
- )
- for ; times > 0; times-- {
- if labels, err = d.Downloader.GetLabels(); err == nil {
- return labels, nil
- }
- select {
- case <-d.ctx.Done():
- return nil, d.ctx.Err()
- case <-time.After(time.Second * time.Duration(d.RetryDelay)):
- }
- }
- return nil, err
-}
-
-// GetIssues returns a repository's issues with retry
-func (d *RetryDownloader) GetIssues(page, perPage int) ([]*Issue, bool, error) {
- var (
- times = d.RetryTimes
- issues []*Issue
- isEnd bool
- err error
- )
- for ; times > 0; times-- {
- if issues, isEnd, err = d.Downloader.GetIssues(page, perPage); err == nil {
- return issues, isEnd, nil
- }
- select {
- case <-d.ctx.Done():
- return nil, false, d.ctx.Err()
- case <-time.After(time.Second * time.Duration(d.RetryDelay)):
- }
- }
- return nil, false, err
-}
-
-// GetComments returns a repository's comments with retry
-func (d *RetryDownloader) GetComments(issueNumber int64) ([]*Comment, error) {
- var (
- times = d.RetryTimes
- comments []*Comment
- err error
- )
- for ; times > 0; times-- {
- if comments, err = d.Downloader.GetComments(issueNumber); err == nil {
- return comments, nil
- }
- select {
- case <-d.ctx.Done():
- return nil, d.ctx.Err()
- case <-time.After(time.Second * time.Duration(d.RetryDelay)):
- }
- }
- return nil, err
-}
-
-// GetPullRequests returns a repository's pull requests with retry
-func (d *RetryDownloader) GetPullRequests(page, perPage int) ([]*PullRequest, bool, error) {
- var (
- times = d.RetryTimes
- prs []*PullRequest
- err error
- isEnd bool
- )
- for ; times > 0; times-- {
- if prs, isEnd, err = d.Downloader.GetPullRequests(page, perPage); err == nil {
- return prs, isEnd, nil
- }
- select {
- case <-d.ctx.Done():
- return nil, false, d.ctx.Err()
- case <-time.After(time.Second * time.Duration(d.RetryDelay)):
- }
- }
- return nil, false, err
-}
-
-// GetReviews returns pull requests reviews
-func (d *RetryDownloader) GetReviews(pullRequestNumber int64) ([]*Review, error) {
- var (
- times = d.RetryTimes
- reviews []*Review
- err error
- )
- for ; times > 0; times-- {
- if reviews, err = d.Downloader.GetReviews(pullRequestNumber); err == nil {
- return reviews, nil
- }
- select {
- case <-d.ctx.Done():
- return nil, d.ctx.Err()
- case <-time.After(time.Second * time.Duration(d.RetryDelay)):
- }
- }
- return nil, err
-}
diff --git a/modules/migrations/base/error.go b/modules/migrations/base/error.go
new file mode 100644
index 0000000000..40ddcf4b75
--- /dev/null
+++ b/modules/migrations/base/error.go
@@ -0,0 +1,26 @@
+// 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 base
+
+import "fmt"
+
+// ErrNotSupported represents status if a downloader do not supported something.
+type ErrNotSupported struct {
+ Entity string
+}
+
+// IsErrNotSupported checks if an error is an ErrNotSupported
+func IsErrNotSupported(err error) bool {
+ _, ok := err.(ErrNotSupported)
+ return ok
+}
+
+// Error return error message
+func (err ErrNotSupported) Error() string {
+ if len(err.Entity) != 0 {
+ return fmt.Sprintf("'%s' not supported", err.Entity)
+ }
+ return "not supported"
+}
diff --git a/modules/migrations/base/milestone.go b/modules/migrations/base/milestone.go
index 8736aa6cfd..921968fcb5 100644
--- a/modules/migrations/base/milestone.go
+++ b/modules/migrations/base/milestone.go
@@ -15,5 +15,5 @@ type Milestone struct {
Created time.Time
Updated *time.Time
Closed *time.Time
- State string
+ State string // open, closed
}
diff --git a/modules/migrations/base/null_downloader.go b/modules/migrations/base/null_downloader.go
new file mode 100644
index 0000000000..a93c20339b
--- /dev/null
+++ b/modules/migrations/base/null_downloader.go
@@ -0,0 +1,82 @@
+// 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 base
+
+import (
+ "context"
+ "net/url"
+)
+
+// NullDownloader implements a blank downloader
+type NullDownloader struct {
+}
+
+var (
+ _ Downloader = &NullDownloader{}
+)
+
+// SetContext set context
+func (n NullDownloader) SetContext(_ context.Context) {}
+
+// GetRepoInfo returns a repository information
+func (n NullDownloader) GetRepoInfo() (*Repository, error) {
+ return nil, &ErrNotSupported{Entity: "RepoInfo"}
+}
+
+// GetTopics return repository topics
+func (n NullDownloader) GetTopics() ([]string, error) {
+ return nil, &ErrNotSupported{Entity: "Topics"}
+}
+
+// GetMilestones returns milestones
+func (n NullDownloader) GetMilestones() ([]*Milestone, error) {
+ return nil, &ErrNotSupported{Entity: "Milestones"}
+}
+
+// GetReleases returns releases
+func (n NullDownloader) GetReleases() ([]*Release, error) {
+ return nil, &ErrNotSupported{Entity: "Releases"}
+}
+
+// GetLabels returns labels
+func (n NullDownloader) GetLabels() ([]*Label, error) {
+ return nil, &ErrNotSupported{Entity: "Labels"}
+}
+
+// GetIssues returns issues according start and limit
+func (n NullDownloader) GetIssues(page, perPage int) ([]*Issue, bool, error) {
+ return nil, false, &ErrNotSupported{Entity: "Issues"}
+}
+
+// GetComments returns comments according issueNumber
+func (n NullDownloader) GetComments(issueNumber int64) ([]*Comment, error) {
+ return nil, &ErrNotSupported{Entity: "Comments"}
+}
+
+// GetPullRequests returns pull requests according page and perPage
+func (n NullDownloader) GetPullRequests(page, perPage int) ([]*PullRequest, bool, error) {
+ return nil, false, &ErrNotSupported{Entity: "PullRequests"}
+}
+
+// GetReviews returns pull requests review
+func (n NullDownloader) GetReviews(pullRequestNumber int64) ([]*Review, error) {
+ return nil, &ErrNotSupported{Entity: "Reviews"}
+}
+
+// FormatCloneURL add authentification into remote URLs
+func (n NullDownloader) FormatCloneURL(opts MigrateOptions, remoteAddr string) (string, error) {
+ if len(opts.AuthToken) > 0 || len(opts.AuthUsername) > 0 {
+ u, err := url.Parse(remoteAddr)
+ if err != nil {
+ return "", err
+ }
+ u.User = url.UserPassword(opts.AuthUsername, opts.AuthPassword)
+ if len(opts.AuthToken) > 0 {
+ u.User = url.UserPassword("oauth2", opts.AuthToken)
+ }
+ return u.String(), nil
+ }
+ return remoteAddr, nil
+}
diff --git a/modules/migrations/base/retry_downloader.go b/modules/migrations/base/retry_downloader.go
new file mode 100644
index 0000000000..eeb3cabbc1
--- /dev/null
+++ b/modules/migrations/base/retry_downloader.go
@@ -0,0 +1,247 @@
+// 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 base
+
+import (
+ "context"
+ "time"
+)
+
+var (
+ _ Downloader = &RetryDownloader{}
+)
+
+// RetryDownloader retry the downloads
+type RetryDownloader struct {
+ Downloader
+ ctx context.Context
+ RetryTimes int // the total execute times
+ RetryDelay int // time to delay seconds
+}
+
+// NewRetryDownloader creates a retry downloader
+func NewRetryDownloader(ctx context.Context, downloader Downloader, retryTimes, retryDelay int) *RetryDownloader {
+ return &RetryDownloader{
+ Downloader: downloader,
+ ctx: ctx,
+ RetryTimes: retryTimes,
+ RetryDelay: retryDelay,
+ }
+}
+
+// SetContext set context
+func (d *RetryDownloader) SetContext(ctx context.Context) {
+ d.ctx = ctx
+ d.Downloader.SetContext(ctx)
+}
+
+// GetRepoInfo returns a repository information with retry
+func (d *RetryDownloader) GetRepoInfo() (*Repository, error) {
+ var (
+ times = d.RetryTimes
+ repo *Repository
+ err error
+ )
+ for ; times > 0; times-- {
+ if repo, err = d.Downloader.GetRepoInfo(); err == nil {
+ return repo, nil
+ }
+ if IsErrNotSupported(err) {
+ return nil, err
+ }
+ select {
+ case <-d.ctx.Done():
+ return nil, d.ctx.Err()
+ case <-time.After(time.Second * time.Duration(d.RetryDelay)):
+ }
+ }
+ return nil, err
+}
+
+// GetTopics returns a repository's topics with retry
+func (d *RetryDownloader) GetTopics() ([]string, error) {
+ var (
+ times = d.RetryTimes
+ topics []string
+ err error
+ )
+ for ; times > 0; times-- {
+ if topics, err = d.Downloader.GetTopics(); err == nil {
+ return topics, nil
+ }
+ if IsErrNotSupported(err) {
+ return nil, err
+ }
+ select {
+ case <-d.ctx.Done():
+ return nil, d.ctx.Err()
+ case <-time.After(time.Second * time.Duration(d.RetryDelay)):
+ }
+ }
+ return nil, err
+}
+
+// GetMilestones returns a repository's milestones with retry
+func (d *RetryDownloader) GetMilestones() ([]*Milestone, error) {
+ var (
+ times = d.RetryTimes
+ milestones []*Milestone
+ err error
+ )
+ for ; times > 0; times-- {
+ if milestones, err = d.Downloader.GetMilestones(); err == nil {
+ return milestones, nil
+ }
+ if IsErrNotSupported(err) {
+ return nil, err
+ }
+ select {
+ case <-d.ctx.Done():
+ return nil, d.ctx.Err()
+ case <-time.After(time.Second * time.Duration(d.RetryDelay)):
+ }
+ }
+ return nil, err
+}
+
+// GetReleases returns a repository's releases with retry
+func (d *RetryDownloader) GetReleases() ([]*Release, error) {
+ var (
+ times = d.RetryTimes
+ releases []*Release
+ err error
+ )
+ for ; times > 0; times-- {
+ if releases, err = d.Downloader.GetReleases(); err == nil {
+ return releases, nil
+ }
+ if IsErrNotSupported(err) {
+ return nil, err
+ }
+ select {
+ case <-d.ctx.Done():
+ return nil, d.ctx.Err()
+ case <-time.After(time.Second * time.Duration(d.RetryDelay)):
+ }
+ }
+ return nil, err
+}
+
+// GetLabels returns a repository's labels with retry
+func (d *RetryDownloader) GetLabels() ([]*Label, error) {
+ var (
+ times = d.RetryTimes
+ labels []*Label
+ err error
+ )
+ for ; times > 0; times-- {
+ if labels, err = d.Downloader.GetLabels(); err == nil {
+ return labels, nil
+ }
+ if IsErrNotSupported(err) {
+ return nil, err
+ }
+ select {
+ case <-d.ctx.Done():
+ return nil, d.ctx.Err()
+ case <-time.After(time.Second * time.Duration(d.RetryDelay)):
+ }
+ }
+ return nil, err
+}
+
+// GetIssues returns a repository's issues with retry
+func (d *RetryDownloader) GetIssues(page, perPage int) ([]*Issue, bool, error) {
+ var (
+ times = d.RetryTimes
+ issues []*Issue
+ isEnd bool
+ err error
+ )
+ for ; times > 0; times-- {
+ if issues, isEnd, err = d.Downloader.GetIssues(page, perPage); err == nil {
+ return issues, isEnd, nil
+ }
+ if IsErrNotSupported(err) {
+ return nil, false, err
+ }
+ select {
+ case <-d.ctx.Done():
+ return nil, false, d.ctx.Err()
+ case <-time.After(time.Second * time.Duration(d.RetryDelay)):
+ }
+ }
+ return nil, false, err
+}
+
+// GetComments returns a repository's comments with retry
+func (d *RetryDownloader) GetComments(issueNumber int64) ([]*Comment, error) {
+ var (
+ times = d.RetryTimes
+ comments []*Comment
+ err error
+ )
+ for ; times > 0; times-- {
+ if comments, err = d.Downloader.GetComments(issueNumber); err == nil {
+ return comments, nil
+ }
+ if IsErrNotSupported(err) {
+ return nil, err
+ }
+ select {
+ case <-d.ctx.Done():
+ return nil, d.ctx.Err()
+ case <-time.After(time.Second * time.Duration(d.RetryDelay)):
+ }
+ }
+ return nil, err
+}
+
+// GetPullRequests returns a repository's pull requests with retry
+func (d *RetryDownloader) GetPullRequests(page, perPage int) ([]*PullRequest, bool, error) {
+ var (
+ times = d.RetryTimes
+ prs []*PullRequest
+ err error
+ isEnd bool
+ )
+ for ; times > 0; times-- {
+ if prs, isEnd, err = d.Downloader.GetPullRequests(page, perPage); err == nil {
+ return prs, isEnd, nil
+ }
+ if IsErrNotSupported(err) {
+ return nil, false, err
+ }
+ select {
+ case <-d.ctx.Done():
+ return nil, false, d.ctx.Err()
+ case <-time.After(time.Second * time.Duration(d.RetryDelay)):
+ }
+ }
+ return nil, false, err
+}
+
+// GetReviews returns pull requests reviews
+func (d *RetryDownloader) GetReviews(pullRequestNumber int64) ([]*Review, error) {
+ var (
+ times = d.RetryTimes
+ reviews []*Review
+ err error
+ )
+ for ; times > 0; times-- {
+ if reviews, err = d.Downloader.GetReviews(pullRequestNumber); err == nil {
+ return reviews, nil
+ }
+ if IsErrNotSupported(err) {
+ return nil, err
+ }
+ select {
+ case <-d.ctx.Done():
+ return nil, d.ctx.Err()
+ case <-time.After(time.Second * time.Duration(d.RetryDelay)):
+ }
+ }
+ return nil, err
+}
diff --git a/modules/migrations/error.go b/modules/migrations/error.go
index 462ba29026..1c77fa9f2f 100644
--- a/modules/migrations/error.go
+++ b/modules/migrations/error.go
@@ -12,9 +12,6 @@ import (
)
var (
- // ErrNotSupported returns the error not supported
- ErrNotSupported = errors.New("not supported")
-
// ErrRepoNotCreated returns the error that repository not created
ErrRepoNotCreated = errors.New("repository is not created yet")
)
diff --git a/modules/migrations/git.go b/modules/migrations/git.go
index 88222086e4..7e41945474 100644
--- a/modules/migrations/git.go
+++ b/modules/migrations/git.go
@@ -16,6 +16,7 @@ var (
// PlainGitDownloader implements a Downloader interface to clone git from a http/https URL
type PlainGitDownloader struct {
+ base.NullDownloader
ownerName string
repoName string
remoteURL string
@@ -44,42 +45,7 @@ func (g *PlainGitDownloader) GetRepoInfo() (*base.Repository, error) {
}, nil
}
-// GetTopics returns empty list for plain git repo
-func (g *PlainGitDownloader) GetTopics() ([]string, error) {
+// GetTopics return empty string slice
+func (g PlainGitDownloader) GetTopics() ([]string, error) {
return []string{}, nil
}
-
-// GetMilestones returns milestones
-func (g *PlainGitDownloader) GetMilestones() ([]*base.Milestone, error) {
- return nil, ErrNotSupported
-}
-
-// GetLabels returns labels
-func (g *PlainGitDownloader) GetLabels() ([]*base.Label, error) {
- return nil, ErrNotSupported
-}
-
-// GetReleases returns releases
-func (g *PlainGitDownloader) GetReleases() ([]*base.Release, error) {
- return nil, ErrNotSupported
-}
-
-// GetIssues returns issues according page and perPage
-func (g *PlainGitDownloader) GetIssues(page, perPage int) ([]*base.Issue, bool, error) {
- return nil, false, ErrNotSupported
-}
-
-// GetComments returns comments according issueNumber
-func (g *PlainGitDownloader) GetComments(issueNumber int64) ([]*base.Comment, error) {
- return nil, ErrNotSupported
-}
-
-// GetPullRequests returns pull requests according page and perPage
-func (g *PlainGitDownloader) GetPullRequests(start, limit int) ([]*base.PullRequest, bool, error) {
- return nil, false, ErrNotSupported
-}
-
-// GetReviews returns reviews according issue number
-func (g *PlainGitDownloader) GetReviews(issueNumber int64) ([]*base.Review, error) {
- return nil, ErrNotSupported
-}
diff --git a/modules/migrations/gitea_downloader.go b/modules/migrations/gitea_downloader.go
index 0c690464fa..70daf8d5a3 100644
--- a/modules/migrations/gitea_downloader.go
+++ b/modules/migrations/gitea_downloader.go
@@ -69,6 +69,7 @@ func (f *GiteaDownloaderFactory) GitServiceType() structs.GitServiceType {
// GiteaDownloader implements a Downloader interface to get repository information's
type GiteaDownloader struct {
+ base.NullDownloader
ctx context.Context
client *gitea_sdk.Client
repoOwner string
@@ -95,7 +96,7 @@ func NewGiteaDownloader(ctx context.Context, baseURL, repoPath, username, passwo
path := strings.Split(repoPath, "/")
paginationSupport := true
- if err := giteaClient.CheckServerVersionConstraint(">=1.12"); err != nil {
+ if err = giteaClient.CheckServerVersionConstraint(">=1.12"); err != nil {
paginationSupport = false
}
diff --git a/modules/migrations/gitea_uploader.go b/modules/migrations/gitea_uploader.go
index 2c79bd4b0f..3be49b5c6c 100644
--- a/modules/migrations/gitea_uploader.go
+++ b/modules/migrations/gitea_uploader.go
@@ -10,7 +10,6 @@ import (
"context"
"fmt"
"io"
- "net/url"
"os"
"path/filepath"
"strings"
@@ -86,22 +85,6 @@ func (g *GiteaLocalUploader) MaxBatchInsertSize(tp string) int {
return 10
}
-func fullURL(opts base.MigrateOptions, remoteAddr string) (string, error) {
- var fullRemoteAddr = remoteAddr
- if len(opts.AuthToken) > 0 || len(opts.AuthUsername) > 0 {
- u, err := url.Parse(remoteAddr)
- if err != nil {
- return "", err
- }
- u.User = url.UserPassword(opts.AuthUsername, opts.AuthPassword)
- if len(opts.AuthToken) > 0 {
- u.User = url.UserPassword("oauth2", opts.AuthToken)
- }
- fullRemoteAddr = u.String()
- }
- return fullRemoteAddr, nil
-}
-
// CreateRepo creates a repository
func (g *GiteaLocalUploader) CreateRepo(repo *base.Repository, opts base.MigrateOptions) error {
owner, err := models.GetUserByName(g.repoOwner)
@@ -109,10 +92,6 @@ func (g *GiteaLocalUploader) CreateRepo(repo *base.Repository, opts base.Migrate
return err
}
- remoteAddr, err := fullURL(opts, repo.CloneURL)
- if err != nil {
- return err
- }
var r *models.Repository
if opts.MigrateToRepoID <= 0 {
r, err = repo_module.CreateRepository(g.doer, owner, models.CreateRepoOptions{
@@ -138,7 +117,7 @@ func (g *GiteaLocalUploader) CreateRepo(repo *base.Repository, opts base.Migrate
OriginalURL: repo.OriginalURL,
GitServiceType: opts.GitServiceType,
Mirror: repo.IsMirror,
- CloneAddr: remoteAddr,
+ CloneAddr: repo.CloneURL,
Private: repo.IsPrivate,
Wiki: opts.Wiki,
Releases: opts.Releases, // if didn't get releases, then sync them from tags
diff --git a/modules/migrations/github.go b/modules/migrations/github.go
index 178517ba42..4d832387ba 100644
--- a/modules/migrations/github.go
+++ b/modules/migrations/github.go
@@ -65,6 +65,7 @@ func (f *GithubDownloaderV3Factory) GitServiceType() structs.GitServiceType {
// GithubDownloaderV3 implements a Downloader interface to get repository informations
// from github via APIv3
type GithubDownloaderV3 struct {
+ base.NullDownloader
ctx context.Context
client *github.Client
repoOwner string
diff --git a/modules/migrations/gitlab.go b/modules/migrations/gitlab.go
index e3fa956758..a697075ff8 100644
--- a/modules/migrations/gitlab.go
+++ b/modules/migrations/gitlab.go
@@ -63,6 +63,7 @@ func (f *GitlabDownloaderFactory) GitServiceType() structs.GitServiceType {
// - issueSeen, working alongside issueCount, is checked in GetComments() to see whether we
// need to fetch the Issue or PR comments, as Gitlab stores them separately.
type GitlabDownloader struct {
+ base.NullDownloader
ctx context.Context
client *gitlab.Client
repoID int
diff --git a/modules/migrations/gogs.go b/modules/migrations/gogs.go
new file mode 100644
index 0000000000..b616907938
--- /dev/null
+++ b/modules/migrations/gogs.go
@@ -0,0 +1,312 @@
+// 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 migrations
+
+import (
+ "context"
+ "fmt"
+ "net/http"
+ "net/url"
+ "strings"
+ "time"
+
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/migrations/base"
+ "code.gitea.io/gitea/modules/structs"
+
+ "github.com/gogs/go-gogs-client"
+)
+
+var (
+ _ base.Downloader = &GogsDownloader{}
+ _ base.DownloaderFactory = &GogsDownloaderFactory{}
+)
+
+func init() {
+ RegisterDownloaderFactory(&GogsDownloaderFactory{})
+}
+
+// GogsDownloaderFactory defines a gogs downloader factory
+type GogsDownloaderFactory struct {
+}
+
+// New returns a Downloader related to this factory according MigrateOptions
+func (f *GogsDownloaderFactory) New(ctx context.Context, opts base.MigrateOptions) (base.Downloader, error) {
+ u, err := url.Parse(opts.CloneAddr)
+ if err != nil {
+ return nil, err
+ }
+
+ baseURL := u.Scheme + "://" + u.Host
+ repoNameSpace := strings.TrimSuffix(u.Path, ".git")
+ repoNameSpace = strings.Trim(repoNameSpace, "/")
+
+ fields := strings.Split(repoNameSpace, "/")
+ if len(fields) < 2 {
+ return nil, fmt.Errorf("invalid path: %s", repoNameSpace)
+ }
+
+ log.Trace("Create gogs downloader. BaseURL: %s RepoOwner: %s RepoName: %s", baseURL, fields[0], fields[1])
+ return NewGogsDownloader(ctx, baseURL, opts.AuthUsername, opts.AuthPassword, opts.AuthToken, fields[0], fields[1]), nil
+}
+
+// GitServiceType returns the type of git service
+func (f *GogsDownloaderFactory) GitServiceType() structs.GitServiceType {
+ return structs.GogsService
+}
+
+// GogsDownloader implements a Downloader interface to get repository informations
+// from gogs via API
+type GogsDownloader struct {
+ base.NullDownloader
+ ctx context.Context
+ client *gogs.Client
+ baseURL string
+ repoOwner string
+ repoName string
+ userName string
+ password string
+ openIssuesFinished bool
+ openIssuesPages int
+ transport http.RoundTripper
+}
+
+// SetContext set context
+func (g *GogsDownloader) SetContext(ctx context.Context) {
+ g.ctx = ctx
+}
+
+// NewGogsDownloader creates a gogs Downloader via gogs API
+func NewGogsDownloader(ctx context.Context, baseURL, userName, password, token, repoOwner, repoName string) *GogsDownloader {
+ var downloader = GogsDownloader{
+ ctx: ctx,
+ baseURL: baseURL,
+ userName: userName,
+ password: password,
+ repoOwner: repoOwner,
+ repoName: repoName,
+ }
+
+ var client *gogs.Client
+ if len(token) != 0 {
+ client = gogs.NewClient(baseURL, token)
+ downloader.userName = token
+ } else {
+ downloader.transport = &http.Transport{
+ Proxy: func(req *http.Request) (*url.URL, error) {
+ req.SetBasicAuth(userName, password)
+ return nil, nil
+ },
+ }
+
+ client = gogs.NewClient(baseURL, "")
+ client.SetHTTPClient(&http.Client{
+ Transport: &downloader,
+ })
+ }
+
+ downloader.client = client
+ return &downloader
+}
+
+// RoundTrip wraps the provided request within this downloader's context and passes it to our internal http.Transport.
+// This implements http.RoundTripper and makes the gogs client requests cancellable even though it is not cancellable itself
+func (g *GogsDownloader) RoundTrip(req *http.Request) (*http.Response, error) {
+ return g.transport.RoundTrip(req.WithContext(g.ctx))
+}
+
+// GetRepoInfo returns a repository information
+func (g *GogsDownloader) GetRepoInfo() (*base.Repository, error) {
+ gr, err := g.client.GetRepo(g.repoOwner, g.repoName)
+ if err != nil {
+ return nil, err
+ }
+
+ // convert gogs repo to stand Repo
+ return &base.Repository{
+ Owner: g.repoOwner,
+ Name: g.repoName,
+ IsPrivate: gr.Private,
+ Description: gr.Description,
+ CloneURL: gr.CloneURL,
+ OriginalURL: gr.HTMLURL,
+ DefaultBranch: gr.DefaultBranch,
+ }, nil
+}
+
+// GetMilestones returns milestones
+func (g *GogsDownloader) GetMilestones() ([]*base.Milestone, error) {
+ var perPage = 100
+ var milestones = make([]*base.Milestone, 0, perPage)
+
+ ms, err := g.client.ListRepoMilestones(g.repoOwner, g.repoName)
+ if err != nil {
+ return nil, err
+ }
+
+ t := time.Now()
+
+ for _, m := range ms {
+ milestones = append(milestones, &base.Milestone{
+ Title: m.Title,
+ Description: m.Description,
+ Deadline: m.Deadline,
+ State: string(m.State),
+ Created: t,
+ Updated: &t,
+ Closed: m.Closed,
+ })
+ }
+
+ return milestones, nil
+}
+
+// GetLabels returns labels
+func (g *GogsDownloader) GetLabels() ([]*base.Label, error) {
+ var perPage = 100
+ var labels = make([]*base.Label, 0, perPage)
+ ls, err := g.client.ListRepoLabels(g.repoOwner, g.repoName)
+ if err != nil {
+ return nil, err
+ }
+
+ for _, label := range ls {
+ labels = append(labels, convertGogsLabel(label))
+ }
+
+ return labels, nil
+}
+
+// GetIssues returns issues according start and limit, perPage is not supported
+func (g *GogsDownloader) GetIssues(page, _ int) ([]*base.Issue, bool, error) {
+ var state string
+ if g.openIssuesFinished {
+ state = string(gogs.STATE_CLOSED)
+ page -= g.openIssuesPages
+ } else {
+ state = string(gogs.STATE_OPEN)
+ g.openIssuesPages = page
+ }
+
+ issues, isEnd, err := g.getIssues(page, state)
+ if err != nil {
+ return nil, false, err
+ }
+
+ if isEnd {
+ if g.openIssuesFinished {
+ return issues, true, nil
+ }
+ g.openIssuesFinished = true
+ }
+
+ return issues, false, nil
+}
+
+func (g *GogsDownloader) getIssues(page int, state string) ([]*base.Issue, bool, error) {
+ var allIssues = make([]*base.Issue, 0, 10)
+
+ issues, err := g.client.ListRepoIssues(g.repoOwner, g.repoName, gogs.ListIssueOption{
+ Page: page,
+ State: state,
+ })
+ if err != nil {
+ return nil, false, fmt.Errorf("error while listing repos: %v", err)
+ }
+
+ for _, issue := range issues {
+ if issue.PullRequest != nil {
+ continue
+ }
+ allIssues = append(allIssues, convertGogsIssue(issue))
+ }
+
+ return allIssues, len(issues) == 0, nil
+}
+
+// GetComments returns comments according issueNumber
+func (g *GogsDownloader) GetComments(issueNumber int64) ([]*base.Comment, error) {
+ var allComments = make([]*base.Comment, 0, 100)
+
+ comments, err := g.client.ListIssueComments(g.repoOwner, g.repoName, issueNumber)
+ if err != nil {
+ return nil, fmt.Errorf("error while listing repos: %v", err)
+ }
+ for _, comment := range comments {
+ if len(comment.Body) == 0 || comment.Poster == nil {
+ continue
+ }
+ allComments = append(allComments, &base.Comment{
+ IssueIndex: issueNumber,
+ PosterID: comment.Poster.ID,
+ PosterName: comment.Poster.Login,
+ PosterEmail: comment.Poster.Email,
+ Content: comment.Body,
+ Created: comment.Created,
+ Updated: comment.Updated,
+ })
+ }
+
+ return allComments, nil
+}
+
+// GetTopics return repository topics
+func (g *GogsDownloader) GetTopics() ([]string, error) {
+ return []string{}, nil
+}
+
+// FormatCloneURL add authentification into remote URLs
+func (g *GogsDownloader) FormatCloneURL(opts MigrateOptions, remoteAddr string) (string, error) {
+ if len(opts.AuthToken) > 0 || len(opts.AuthUsername) > 0 {
+ u, err := url.Parse(remoteAddr)
+ if err != nil {
+ return "", err
+ }
+ if len(opts.AuthToken) != 0 {
+ u.User = url.UserPassword(opts.AuthToken, "")
+ } else {
+ u.User = url.UserPassword(opts.AuthUsername, opts.AuthPassword)
+ }
+ return u.String(), nil
+ }
+ return remoteAddr, nil
+}
+
+func convertGogsIssue(issue *gogs.Issue) *base.Issue {
+ var milestone string
+ if issue.Milestone != nil {
+ milestone = issue.Milestone.Title
+ }
+ var labels = make([]*base.Label, 0, len(issue.Labels))
+ for _, l := range issue.Labels {
+ labels = append(labels, convertGogsLabel(l))
+ }
+
+ var closed *time.Time
+ if issue.State == gogs.STATE_CLOSED {
+ // gogs client haven't provide closed, so we use updated instead
+ closed = &issue.Updated
+ }
+
+ return &base.Issue{
+ Title: issue.Title,
+ Number: issue.Index,
+ PosterName: issue.Poster.Login,
+ PosterEmail: issue.Poster.Email,
+ Content: issue.Body,
+ Milestone: milestone,
+ State: string(issue.State),
+ Created: issue.Created,
+ Labels: labels,
+ Closed: closed,
+ }
+}
+
+func convertGogsLabel(label *gogs.Label) *base.Label {
+ return &base.Label{
+ Name: label.Name,
+ Color: label.Color,
+ }
+}
diff --git a/modules/migrations/gogs_test.go b/modules/migrations/gogs_test.go
new file mode 100644
index 0000000000..c240ae6432
--- /dev/null
+++ b/modules/migrations/gogs_test.go
@@ -0,0 +1,122 @@
+// 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 migrations
+
+import (
+ "context"
+ "net/http"
+ "os"
+ "testing"
+ "time"
+
+ "code.gitea.io/gitea/modules/migrations/base"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGogsDownloadRepo(t *testing.T) {
+ // Skip tests if Gogs token is not found
+ gogsPersonalAccessToken := os.Getenv("GOGS_READ_TOKEN")
+ if len(gogsPersonalAccessToken) == 0 {
+ t.Skip("skipped test because GOGS_READ_TOKEN was not in the environment")
+ }
+
+ resp, err := http.Get("https://try.gogs.io/lunnytest/TESTREPO")
+ if err != nil || resp.StatusCode/100 != 2 {
+ // skip and don't run test
+ t.Skipf("visit test repo failed, ignored")
+ return
+ }
+
+ downloader := NewGogsDownloader(context.Background(), "https://try.gogs.io", "", "", gogsPersonalAccessToken, "lunnytest", "TESTREPO")
+ repo, err := downloader.GetRepoInfo()
+ assert.NoError(t, err)
+
+ assert.EqualValues(t, &base.Repository{
+ Name: "TESTREPO",
+ Owner: "lunnytest",
+ Description: "",
+ CloneURL: "https://try.gogs.io/lunnytest/TESTREPO.git",
+ }, repo)
+
+ milestones, err := downloader.GetMilestones()
+ assert.NoError(t, err)
+ assert.True(t, len(milestones) == 1)
+
+ for _, milestone := range milestones {
+ switch milestone.Title {
+ case "1.0":
+ assert.EqualValues(t, "open", milestone.State)
+ }
+ }
+
+ labels, err := downloader.GetLabels()
+ assert.NoError(t, err)
+ assert.Len(t, labels, 7)
+ for _, l := range labels {
+ switch l.Name {
+ case "bug":
+ assertLabelEqual(t, "bug", "ee0701", "", l)
+ case "duplicated":
+ assertLabelEqual(t, "duplicated", "cccccc", "", l)
+ case "enhancement":
+ assertLabelEqual(t, "enhancement", "84b6eb", "", l)
+ case "help wanted":
+ assertLabelEqual(t, "help wanted", "128a0c", "", l)
+ case "invalid":
+ assertLabelEqual(t, "invalid", "e6e6e6", "", l)
+ case "question":
+ assertLabelEqual(t, "question", "cc317c", "", l)
+ case "wontfix":
+ assertLabelEqual(t, "wontfix", "ffffff", "", l)
+ }
+ }
+
+ _, err = downloader.GetReleases()
+ assert.Error(t, err)
+
+ // downloader.GetIssues()
+ issues, isEnd, err := downloader.GetIssues(1, 8)
+ assert.NoError(t, err)
+ assert.EqualValues(t, 1, len(issues))
+ assert.False(t, isEnd)
+
+ assert.EqualValues(t, []*base.Issue{
+ {
+ Number: 1,
+ Title: "test",
+ Content: "test",
+ Milestone: "",
+ PosterName: "lunny",
+ PosterEmail: "xiaolunwen@gmail.com",
+ State: "open",
+ Created: time.Date(2019, 06, 11, 8, 16, 44, 0, time.UTC),
+ Labels: []*base.Label{
+ {
+ Name: "bug",
+ Color: "ee0701",
+ },
+ },
+ },
+ }, issues)
+
+ // downloader.GetComments()
+ comments, err := downloader.GetComments(1)
+ assert.NoError(t, err)
+ assert.EqualValues(t, 1, len(comments))
+ assert.EqualValues(t, []*base.Comment{
+ {
+ PosterName: "lunny",
+ PosterEmail: "xiaolunwen@gmail.com",
+ Created: time.Date(2019, 06, 11, 8, 19, 50, 0, time.UTC),
+ Updated: time.Date(2019, 06, 11, 8, 19, 50, 0, time.UTC),
+ Content: `1111`,
+ },
+ }, comments)
+
+ // downloader.GetPullRequests()
+ _, _, err = downloader.GetPullRequests(1, 3)
+ assert.Error(t, err)
+}
diff --git a/modules/migrations/migrate.go b/modules/migrations/migrate.go
index 4c15626e57..b9c17478a9 100644
--- a/modules/migrations/migrate.go
+++ b/modules/migrations/migrate.go
@@ -133,15 +133,22 @@ func newDownloader(ctx context.Context, ownerName string, opts base.MigrateOptio
func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts base.MigrateOptions) error {
repo, err := downloader.GetRepoInfo()
if err != nil {
- return err
+ if !base.IsErrNotSupported(err) {
+ return err
+ }
+ log.Info("migrating repo infos is not supported, ignored")
}
repo.IsPrivate = opts.Private
repo.IsMirror = opts.Mirror
if opts.Description != "" {
repo.Description = opts.Description
}
+ if repo.CloneURL, err = downloader.FormatCloneURL(opts, repo.CloneURL); err != nil {
+ return err
+ }
+
log.Trace("migrating git data")
- if err := uploader.CreateRepo(repo, opts); err != nil {
+ if err = uploader.CreateRepo(repo, opts); err != nil {
return err
}
defer uploader.Close()
@@ -149,10 +156,13 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
log.Trace("migrating topics")
topics, err := downloader.GetTopics()
if err != nil {
- return err
+ if !base.IsErrNotSupported(err) {
+ return err
+ }
+ log.Warn("migrating topics is not supported, ignored")
}
- if len(topics) > 0 {
- if err := uploader.CreateTopics(topics...); err != nil {
+ if len(topics) != 0 {
+ if err = uploader.CreateTopics(topics...); err != nil {
return err
}
}
@@ -161,7 +171,10 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
log.Trace("migrating milestones")
milestones, err := downloader.GetMilestones()
if err != nil {
- return err
+ if !base.IsErrNotSupported(err) {
+ return err
+ }
+ log.Warn("migrating milestones is not supported, ignored")
}
msBatchSize := uploader.MaxBatchInsertSize("milestone")
@@ -181,7 +194,10 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
log.Trace("migrating labels")
labels, err := downloader.GetLabels()
if err != nil {
- return err
+ if !base.IsErrNotSupported(err) {
+ return err
+ }
+ log.Warn("migrating labels is not supported, ignored")
}
lbBatchSize := uploader.MaxBatchInsertSize("label")
@@ -201,7 +217,10 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
log.Trace("migrating releases")
releases, err := downloader.GetReleases()
if err != nil {
- return err
+ if !base.IsErrNotSupported(err) {
+ return err
+ }
+ log.Warn("migrating releases is not supported, ignored")
}
relBatchSize := uploader.MaxBatchInsertSize("release")
@@ -210,14 +229,14 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
relBatchSize = len(releases)
}
- if err := uploader.CreateReleases(releases[:relBatchSize]...); err != nil {
+ if err = uploader.CreateReleases(releases[:relBatchSize]...); err != nil {
return err
}
releases = releases[relBatchSize:]
}
// Once all releases (if any) are inserted, sync any remaining non-release tags
- if err := uploader.SyncTags(); err != nil {
+ if err = uploader.SyncTags(); err != nil {
return err
}
}
@@ -234,7 +253,11 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
for i := 1; ; i++ {
issues, isEnd, err := downloader.GetIssues(i, issueBatchSize)
if err != nil {
- return err
+ if !base.IsErrNotSupported(err) {
+ return err
+ }
+ log.Warn("migrating issues is not supported, ignored")
+ break
}
if err := uploader.CreateIssues(issues...); err != nil {
@@ -247,13 +270,16 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
log.Trace("migrating issue %d's comments", issue.Number)
comments, err := downloader.GetComments(issue.Number)
if err != nil {
- return err
+ if !base.IsErrNotSupported(err) {
+ return err
+ }
+ log.Warn("migrating comments is not supported, ignored")
}
allComments = append(allComments, comments...)
if len(allComments) >= commentBatchSize {
- if err := uploader.CreateComments(allComments[:commentBatchSize]...); err != nil {
+ if err = uploader.CreateComments(allComments[:commentBatchSize]...); err != nil {
return err
}
@@ -262,7 +288,7 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
}
if len(allComments) > 0 {
- if err := uploader.CreateComments(allComments...); err != nil {
+ if err = uploader.CreateComments(allComments...); err != nil {
return err
}
}
@@ -280,7 +306,11 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
for i := 1; ; i++ {
prs, isEnd, err := downloader.GetPullRequests(i, prBatchSize)
if err != nil {
- return err
+ if !base.IsErrNotSupported(err) {
+ return err
+ }
+ log.Warn("migrating pull requests is not supported, ignored")
+ break
}
if err := uploader.CreatePullRequests(prs...); err != nil {
@@ -294,20 +324,23 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
log.Trace("migrating pull request %d's comments", pr.Number)
comments, err := downloader.GetComments(pr.Number)
if err != nil {
- return err
+ if !base.IsErrNotSupported(err) {
+ return err
+ }
+ log.Warn("migrating comments is not supported, ignored")
}
allComments = append(allComments, comments...)
if len(allComments) >= commentBatchSize {
- if err := uploader.CreateComments(allComments[:commentBatchSize]...); err != nil {
+ if err = uploader.CreateComments(allComments[:commentBatchSize]...); err != nil {
return err
}
allComments = allComments[commentBatchSize:]
}
}
if len(allComments) > 0 {
- if err := uploader.CreateComments(allComments...); err != nil {
+ if err = uploader.CreateComments(allComments...); err != nil {
return err
}
}
@@ -323,26 +356,30 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
}
reviews, err := downloader.GetReviews(number)
+ if err != nil {
+ if !base.IsErrNotSupported(err) {
+ return err
+ }
+ log.Warn("migrating reviews is not supported, ignored")
+ break
+ }
if pr.OriginalNumber > 0 {
for i := range reviews {
reviews[i].IssueIndex = pr.Number
}
}
- if err != nil {
- return err
- }
allReviews = append(allReviews, reviews...)
if len(allReviews) >= reviewBatchSize {
- if err := uploader.CreateReviews(allReviews[:reviewBatchSize]...); err != nil {
+ if err = uploader.CreateReviews(allReviews[:reviewBatchSize]...); err != nil {
return err
}
allReviews = allReviews[reviewBatchSize:]
}
}
if len(allReviews) > 0 {
- if err := uploader.CreateReviews(allReviews...); err != nil {
+ if err = uploader.CreateReviews(allReviews...); err != nil {
return err
}
}
diff --git a/modules/migrations/restore.go b/modules/migrations/restore.go
index 5550aaeb03..e1ab408e41 100644
--- a/modules/migrations/restore.go
+++ b/modules/migrations/restore.go
@@ -19,6 +19,7 @@ import (
// RepositoryRestorer implements an Downloader from the local directory
type RepositoryRestorer struct {
+ base.NullDownloader
ctx context.Context
baseDir string
repoOwner string
diff --git a/modules/structs/repo.go b/modules/structs/repo.go
index a4eff8b162..d588813b21 100644
--- a/modules/structs/repo.go
+++ b/modules/structs/repo.go
@@ -280,5 +280,6 @@ var (
GithubService,
GitlabService,
GiteaService,
+ GogsService,
}
)
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 30fa5f8a73..69cfb29044 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -776,6 +776,7 @@ migrate.github.description = Migrating data from Github.com or Github Enterprise
migrate.git.description = Migrating or Mirroring git data from Git services
migrate.gitlab.description = Migrating data from GitLab.com or Self-Hosted gitlab server.
migrate.gitea.description = Migrating data from Gitea.com or Self-Hosted Gitea server.
+migrate.gogs.description = Migrating data from notabug.org or other Self-Hosted Gogs server.
mirror_from = mirror of
forked_from = forked from
diff --git a/public/img/svg/gitea-gogs.svg b/public/img/svg/gitea-gogs.svg
new file mode 100644
index 0000000000..e34e81a523
--- /dev/null
+++ b/public/img/svg/gitea-gogs.svg
@@ -0,0 +1 @@
+<svg viewBox="0 0 640 640" class="svg gitea-gogs" width="16" height="16" aria-hidden="true"><path d="M250.368 634.375c-1.445-1.719-5.882-14.218-9.861-27.776-6.693-22.806-7.834-24.852-15.253-27.32-18.366-6.114-58.769-27.528-76.961-40.792l-19.513-14.226-13.658 2.87a38833.04 38833.04 0 00-27.532 5.797c-7.63 1.61-15.629 2.28-17.775 1.49-5.153-1.9-67.213-105.858-67.213-112.59 0-3.117 7.884-13.005 19.58-24.553l19.579-19.334-2.019-10.845c-2.575-13.836-2.626-77.041-.075-93.016l1.944-12.17-19.505-19.26C11.38 232.059 2.602 221.277 2.602 218.692c0-5.203 57.532-102.157 65.08-109.674 4.66-4.64 5.296-4.602 32.6 1.972 23.225 5.593 28.603 6.17 32.394 3.483 2.5-1.772 11.192-8.08 19.316-14.017 17.467-12.767 46.373-28.038 67.035-35.415 16.18-5.777 14.574-3.303 25.386-39.125 2.961-9.81 6.983-19.11 8.937-20.669 2.492-1.987 23.264-2.634 69.573-2.165l66.02.669 7.263 22.5c10.553 32.692 10.945 33.186 32.986 41.62 22.359 8.557 43.687 20.45 67.505 37.646 9.302 6.716 18.52 11.54 20.813 10.892 22.045-6.226 48.383-11.336 52.287-10.146 4.188 1.278 69.76 109.778 70.033 112.359.013.12.079.517-.02.736-1.145 2.52-9.555 11.185-19.532 21.501l-19.721 20.392 2.16 20c2.747 25.424 2.753 54.731.019 79.072l-2.144 19.072 19.705 20.247c10.837 11.136 18.425 17.638 19.39 23.528 1.26 7.694-59.597 102.142-64.49 107.807-4.608 5.336-10.065 5.135-38.606-1.427l-24.061-5.531-7.159 5.454c-20.202 15.39-52.104 34.238-71.37 42.165-11.903 4.898-22.998 10.19-24.655 11.759-1.657 1.57-5.568 11.854-8.691 22.854-9.693 34.139-2.26 31.25-80.395 31.25-50.676 0-67.912-.77-69.89-3.125zm142.478-129.169c43.26-14.006 81.273-41.624 104.19-75.696 12.313-18.306 13.493-29.43 4.006-37.754-3.452-3.028-28.33-17.778-55.285-32.776-26.955-14.999-49.87-28.499-50.92-30-1.052-1.502-1.93-7.29-1.952-12.864-.081-20.804-17.326-43.277-40.282-52.494-12.372-4.967-34.32-4.466-47.013 1.074-20.895 9.12-37.623 33.977-37.623 55.905 0 21.402 16.363 45.103 37.724 54.642 13.858 6.188 35.787 6.059 50.365-.298 6.238-2.72 12.836-4.945 14.663-4.945 5.463 0 77.218 40.737 78.82 44.749 2.349 5.88-26.722 29.365-50.16 40.522-92.78 44.165-201.16-8.158-221.452-106.91-5.11-24.87-3.26-49.806 5.569-75.08 8.57-24.532 17.004-38.117 35.291-56.841 45.768-46.862 118.154-59.479 180.51-31.463 20.447 9.186 24.754 9.315 34.975 1.05 6.357-5.14 8.004-8.43 8.004-15.99 0-12.71-11.123-22.053-38.15-32.046-49.005-18.119-103.977-17.624-150.994 1.358-59.09 23.858-106.171 78.297-119.34 137.993-4.86 22.031-4.667 63.731.398 85.914 2.26 9.897 9.98 29.702 17.157 44.013 11.422 22.775 16.017 28.883 36.867 49.007 43.93 42.4 87.826 59.46 148.697 57.79 26.8-.736 34.718-1.99 55.935-8.86z" fill="#d4553b"/></svg> \ No newline at end of file
diff --git a/routers/api/v1/repo/migrate.go b/routers/api/v1/repo/migrate.go
index f07599399c..0b829c9dfb 100644
--- a/routers/api/v1/repo/migrate.go
+++ b/routers/api/v1/repo/migrate.go
@@ -18,6 +18,7 @@ import (
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/migrations"
+ "code.gitea.io/gitea/modules/migrations/base"
"code.gitea.io/gitea/modules/notification"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
@@ -217,6 +218,8 @@ func handleMigrateError(ctx *context.APIContext, repoOwner *models.User, remoteA
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("The pattern '%s' is not allowed in a username.", err.(models.ErrNamePatternNotAllowed).Pattern))
case models.IsErrMigrationNotAllowed(err):
ctx.Error(http.StatusUnprocessableEntity, "", err)
+ case base.IsErrNotSupported(err):
+ ctx.Error(http.StatusUnprocessableEntity, "", err)
default:
err = util.URLSanitizedError(err, remoteAddr)
if strings.Contains(err.Error(), "Authentication failed") ||
diff --git a/templates/repo/migrate/gogs.tmpl b/templates/repo/migrate/gogs.tmpl
new file mode 100644
index 0000000000..dd33fd0138
--- /dev/null
+++ b/templates/repo/migrate/gogs.tmpl
@@ -0,0 +1,139 @@
+{{template "base/head" .}}
+<div class="page-content repository new migrate">
+ <div class="ui middle very relaxed page grid">
+ <div class="column">
+ <form class="ui form" action="{{.Link}}" method="post">
+ {{.CsrfTokenHtml}}
+ <h3 class="ui top attached header">
+ {{.i18n.Tr "repo.migrate.migrate" .service.Title}}
+ <input id="service_type" type="hidden" name="service" value="{{.service}}">
+ </h3>
+ <div class="ui attached segment">
+ {{template "base/alert" .}}
+ <div class="inline required field {{if .Err_CloneAddr}}error{{end}}">
+ <label for="clone_addr">{{.i18n.Tr "repo.migrate.clone_address"}}</label>
+ <input id="clone_addr" name="clone_addr" value="{{.clone_addr}}" autofocus required>
+ <span class="help">
+ {{.i18n.Tr "repo.migrate.clone_address_desc"}}{{if .ContextUser.CanImportLocal}} {{.i18n.Tr "repo.migrate.clone_local_path"}}{{end}}
+ {{if .LFSActive}}<br />{{.i18n.Tr "repo.migrate.lfs_mirror_unsupported"}}{{end}}
+ </span>
+ </div>
+
+ <div class="inline field {{if .Err_Auth}}error{{end}}">
+ <label for="auth_token">{{.i18n.Tr "access_token"}}</label>
+ <input id="auth_token" name="auth_token" value="{{.auth_token}}" {{if not .auth_token}} data-need-clear="true" {{end}}>
+ <!-- <a target=”_blank” href="https://docs.gitea.io/en-us/api-usage">{{svg "octicon-question"}}</a> -->
+ </div>
+
+ <div class="inline field">
+ <label>{{.i18n.Tr "repo.migrate_options"}}</label>
+ <div class="ui checkbox">
+ {{if .DisableMirrors}}
+ <input id="mirror" name="mirror" type="checkbox" readonly>
+ <label>{{.i18n.Tr "repo.migrate_options_mirror_disabled"}}</label>
+ {{else}}
+ <input id="mirror" name="mirror" type="checkbox" {{if .mirror}} checked{{end}}>
+ <label>{{.i18n.Tr "repo.migrate_options_mirror_helper" | Safe}}</label>
+ {{end}}
+ </div>
+ </div>
+
+ <span class="help">{{.i18n.Tr "repo.migrate.migrate_items_options"}}</span>
+ <div id="migrate_items">
+ <div class="inline field">
+ <label>{{.i18n.Tr "repo.migrate_items"}}</label>
+ <div class="ui checkbox">
+ <input name="wiki" type="checkbox" {{if .wiki}} checked{{end}}>
+ <label>{{.i18n.Tr "repo.migrate_items_wiki" | Safe}}</label>
+ </div>
+ <div class="ui checkbox">
+ <input name="milestones" type="checkbox" {{if .milestones}} checked{{end}}>
+ <label>{{.i18n.Tr "repo.migrate_items_milestones" | Safe}}</label>
+ </div>
+ </div>
+ <div class="inline field">
+ <label></label>
+ <div class="ui checkbox">
+ <input name="labels" type="checkbox" {{if .labels}} checked{{end}}>
+ <label>{{.i18n.Tr "repo.migrate_items_labels" | Safe}}</label>
+ </div>
+ <div class="ui checkbox">
+ <input name="issues" type="checkbox" {{if .issues}} checked{{end}}>
+ <label>{{.i18n.Tr "repo.migrate_items_issues" | Safe}}</label>
+ </div>
+ </div>
+ <!-- Gogs do not support it
+ <div class="inline field">
+ <label></label>
+ <div class="ui checkbox">
+ <input name="pull_requests" type="checkbox" {{if .pull_requests}} checked{{end}}>
+ <label>{{.i18n.Tr "repo.migrate_items_merge_requests" | Safe}}</label>
+ </div>
+ <div class="ui checkbox">
+ <input name="releases" type="checkbox" {{if .releases}} checked{{end}}>
+ <label>{{.i18n.Tr "repo.migrate_items_releases" | Safe}}</label>
+ </div>
+ </div>
+ -->
+ </div>
+
+ <div class="ui divider"></div>
+
+ <div class="inline required field {{if .Err_Owner}}error{{end}}">
+ <label>{{.i18n.Tr "repo.owner"}}</label>
+ <div class="ui selection owner dropdown">
+ <input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required>
+ <span class="text" title="{{.ContextUser.Name}}">
+ {{avatar .ContextUser}}
+ {{.ContextUser.ShortName 20}}
+ </span>
+ {{svg "octicon-triangle-down" 14 "dropdown icon"}}
+ <div class="menu" title="{{.SignedUser.Name}}">
+ <div class="item" data-value="{{.SignedUser.ID}}">
+ {{avatar .SignedUser}}
+ {{.SignedUser.ShortName 20}}
+ </div>
+ {{range .Orgs}}
+ <div class="item" data-value="{{.ID}}" title="{{.Name}}">
+ {{avatar .}}
+ {{.ShortName 20}}
+ </div>
+ {{end}}
+ </div>
+ </div>
+ </div>
+
+ <div class="inline required field {{if .Err_RepoName}}error{{end}}">
+ <label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label>
+ <input id="repo_name" name="repo_name" value="{{.repo_name}}" required>
+ </div>
+ <div class="inline field">
+ <label>{{.i18n.Tr "repo.visibility"}}</label>
+ <div class="ui checkbox">
+ {{if .IsForcedPrivate}}
+ <input name="private" type="checkbox" checked readonly>
+ <label>{{.i18n.Tr "repo.visibility_helper_forced" | Safe}}</label>
+ {{else}}
+ <input name="private" type="checkbox" {{if .private}} checked{{end}}>
+ <label>{{.i18n.Tr "repo.visibility_helper" | Safe}}</label>
+ {{end}}
+ </div>
+ </div>
+ <div class="inline field {{if .Err_Description}}error{{end}}">
+ <label for="description">{{.i18n.Tr "repo.repo_desc"}}</label>
+ <textarea id="description" name="description">{{.description}}</textarea>
+ </div>
+
+ <div class="inline field">
+ <label></label>
+ <button class="ui green button">
+ {{.i18n.Tr "repo.migrate_repo"}}
+ </button>
+ <a class="ui button" href="{{AppSubUrl}}/">{{.i18n.Tr "cancel"}}</a>
+ </div>
+ </div>
+ </form>
+ </div>
+ </div>
+</div>
+{{template "base/footer" .}}
diff --git a/vendor/github.com/gogs/go-gogs-client/.gitignore b/vendor/github.com/gogs/go-gogs-client/.gitignore
new file mode 100644
index 0000000000..25e241ae48
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/.gitignore
@@ -0,0 +1,25 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+*.test
+*.prof
+.idea
diff --git a/vendor/github.com/gogs/go-gogs-client/LICENSE b/vendor/github.com/gogs/go-gogs-client/LICENSE
new file mode 100644
index 0000000000..18b264d604
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Go Git Service
+
+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/gogs/go-gogs-client/README.md b/vendor/github.com/gogs/go-gogs-client/README.md
new file mode 100644
index 0000000000..ae33bc06f8
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/README.md
@@ -0,0 +1,8 @@
+Gogs API client in Go
+=====================
+
+This package is still in experiment, see [Wiki](https://github.com/gogits/go-gogs-client/wiki) for documentation.
+
+## License
+
+This project is under the MIT License. See the [LICENSE](https://github.com/gogits/gogs/blob/master/LICENSE) file for the full license text. \ No newline at end of file
diff --git a/vendor/github.com/gogs/go-gogs-client/admin_org.go b/vendor/github.com/gogs/go-gogs-client/admin_org.go
new file mode 100644
index 0000000000..28ba8f105c
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/admin_org.go
@@ -0,0 +1,43 @@
+// Copyright 2015 The Gogs 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 gogs
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+)
+
+func (c *Client) AdminCreateOrg(user string, opt CreateOrgOption) (*Organization, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ org := new(Organization)
+ return org, c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/orgs", user),
+ jsonHeader, bytes.NewReader(body), org)
+}
+
+func (c *Client) AdminCreateTeam(user string, opt CreateTeamOption) (*Team, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ team := new(Team)
+ return team, c.getParsedResponse("POST", fmt.Sprintf("/admin/orgs/%s/teams", user),
+ jsonHeader, bytes.NewReader(body), team)
+}
+
+func (c *Client) AdminAddTeamMembership(teamID int64, user string) error {
+ _, err := c.getResponse("PUT", fmt.Sprintf("/admin/teams/%d/members/%s", teamID, user),
+ jsonHeader, nil)
+ return err
+}
+
+func (c *Client) AdminAddTeamRepository(teamID int64, repo string) error {
+ _, err := c.getResponse("PUT", fmt.Sprintf("/admin/teams/%d/repos/%s", teamID, repo),
+ jsonHeader, nil)
+ return err
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/admin_repo.go b/vendor/github.com/gogs/go-gogs-client/admin_repo.go
new file mode 100644
index 0000000000..50ba2be47d
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/admin_repo.go
@@ -0,0 +1,21 @@
+// Copyright 2015 The Gogs 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 gogs
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+)
+
+func (c *Client) AdminCreateRepo(user string, opt CreateRepoOption) (*Repository, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ repo := new(Repository)
+ return repo, c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/repos", user),
+ jsonHeader, bytes.NewReader(body), repo)
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/admin_user.go b/vendor/github.com/gogs/go-gogs-client/admin_user.go
new file mode 100644
index 0000000000..459031d71d
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/admin_user.go
@@ -0,0 +1,68 @@
+// Copyright 2015 The Gogs 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 gogs
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+)
+
+type CreateUserOption struct {
+ SourceID int64 `json:"source_id"`
+ LoginName string `json:"login_name"`
+ Username string `json:"username" binding:"Required;AlphaDashDot;MaxSize(35)"`
+ FullName string `json:"full_name" binding:"MaxSize(100)"`
+ Email string `json:"email" binding:"Required;Email;MaxSize(254)"`
+ Password string `json:"password" binding:"MaxSize(255)"`
+ SendNotify bool `json:"send_notify"`
+}
+
+func (c *Client) AdminCreateUser(opt CreateUserOption) (*User, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ user := new(User)
+ return user, c.getParsedResponse("POST", "/admin/users", jsonHeader, bytes.NewReader(body), user)
+}
+
+type EditUserOption struct {
+ SourceID int64 `json:"source_id"`
+ LoginName string `json:"login_name"`
+ FullName string `json:"full_name" binding:"MaxSize(100)"`
+ Email string `json:"email" binding:"Required;Email;MaxSize(254)"`
+ Password string `json:"password" binding:"MaxSize(255)"`
+ Website string `json:"website" binding:"MaxSize(50)"`
+ Location string `json:"location" binding:"MaxSize(50)"`
+ 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"`
+}
+
+func (c *Client) AdminEditUser(user string, opt EditUserOption) error {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return err
+ }
+ _, err = c.getResponse("PATCH", fmt.Sprintf("/admin/users/%s", user), jsonHeader, bytes.NewReader(body))
+ return err
+}
+
+func (c *Client) AdminDeleteUser(user string) error {
+ _, err := c.getResponse("DELETE", fmt.Sprintf("/admin/users/%s", user), nil, nil)
+ return err
+}
+
+func (c *Client) AdminCreateUserPublicKey(user string, opt CreateKeyOption) (*PublicKey, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ key := new(PublicKey)
+ return key, c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/keys", user), jsonHeader, bytes.NewReader(body), key)
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/gogs.go b/vendor/github.com/gogs/go-gogs-client/gogs.go
new file mode 100644
index 0000000000..83ab8d71c5
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/gogs.go
@@ -0,0 +1,90 @@
+// Copyright 2014 The Gogs 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 gogs
+
+import (
+ "encoding/json"
+ "errors"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "strings"
+)
+
+func Version() string {
+ return "0.13.0"
+}
+
+// Client represents a Gogs API client.
+type Client struct {
+ url string
+ accessToken string
+ client *http.Client
+}
+
+// NewClient initializes and returns an API client.
+func NewClient(url, token string) *Client {
+ return &Client{
+ url: strings.TrimSuffix(url, "/"),
+ accessToken: token,
+ client: &http.Client{},
+ }
+}
+
+// SetHTTPClient replaces default http.Client with user given one.
+func (c *Client) SetHTTPClient(client *http.Client) {
+ c.client = client
+}
+
+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)
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Authorization", "token "+c.accessToken)
+ for k, v := range header {
+ 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)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ data, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ switch resp.StatusCode {
+ case 403:
+ return nil, errors.New("403 Forbidden")
+ case 404:
+ return nil, errors.New("404 Not Found")
+ }
+
+ if resp.StatusCode/100 != 2 {
+ errMap := make(map[string]interface{})
+ if err = json.Unmarshal(data, &errMap); err != nil {
+ return nil, err
+ }
+ return nil, errors.New(errMap["message"].(string))
+ }
+
+ return data, 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)
+ if err != nil {
+ return err
+ }
+ return json.Unmarshal(data, obj)
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/issue.go b/vendor/github.com/gogs/go-gogs-client/issue.go
new file mode 100644
index 0000000000..ec69a35b1e
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/issue.go
@@ -0,0 +1,103 @@
+// Copyright 2016 The Gogs 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 gogs
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "time"
+)
+
+type StateType string
+
+const (
+ STATE_OPEN StateType = "open"
+ STATE_CLOSED StateType = "closed"
+)
+
+type PullRequestMeta struct {
+ HasMerged bool `json:"merged"`
+ Merged *time.Time `json:"merged_at"`
+}
+
+type Issue struct {
+ ID int64 `json:"id"`
+ Index int64 `json:"number"`
+ Poster *User `json:"user"`
+ Title string `json:"title"`
+ Body string `json:"body"`
+ Labels []*Label `json:"labels"`
+ Milestone *Milestone `json:"milestone"`
+ Assignee *User `json:"assignee"`
+ State StateType `json:"state"`
+ Comments int `json:"comments"`
+ Created time.Time `json:"created_at"`
+ Updated time.Time `json:"updated_at"`
+
+ PullRequest *PullRequestMeta `json:"pull_request"`
+}
+
+type ListIssueOption struct {
+ Page int
+ State string
+}
+
+func (c *Client) ListIssues(opt ListIssueOption) ([]*Issue, error) {
+ issues := make([]*Issue, 0, 10)
+ return issues, c.getParsedResponse("GET", fmt.Sprintf("/issues?page=%d&state=%s", opt.Page, opt.State), nil, nil, &issues)
+}
+
+func (c *Client) ListUserIssues(opt ListIssueOption) ([]*Issue, error) {
+ issues := make([]*Issue, 0, 10)
+ return issues, c.getParsedResponse("GET", fmt.Sprintf("/user/issues?page=%d&state=%s", opt.Page, opt.State), nil, nil, &issues)
+}
+
+func (c *Client) ListRepoIssues(owner, repo string, opt ListIssueOption) ([]*Issue, error) {
+ issues := make([]*Issue, 0, 10)
+ return issues, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues?page=%d&state=%s", owner, repo, opt.Page, opt.State), nil, nil, &issues)
+}
+
+func (c *Client) GetIssue(owner, repo string, index int64) (*Issue, error) {
+ issue := new(Issue)
+ return issue, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index), nil, nil, issue)
+}
+
+type CreateIssueOption struct {
+ Title string `json:"title" binding:"Required"`
+ Body string `json:"body"`
+ Assignee string `json:"assignee"`
+ Milestone int64 `json:"milestone"`
+ Labels []int64 `json:"labels"`
+ Closed bool `json:"closed"`
+}
+
+func (c *Client) CreateIssue(owner, repo string, opt CreateIssueOption) (*Issue, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ issue := new(Issue)
+ return issue, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues", owner, repo),
+ jsonHeader, bytes.NewReader(body), issue)
+}
+
+type EditIssueOption struct {
+ Title string `json:"title"`
+ Body *string `json:"body"`
+ Assignee *string `json:"assignee"`
+ Milestone *int64 `json:"milestone"`
+ State *string `json:"state"`
+}
+
+func (c *Client) EditIssue(owner, repo string, index int64, opt EditIssueOption) (*Issue, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ issue := new(Issue)
+ return issue, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index),
+ jsonHeader, bytes.NewReader(body), issue)
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/issue_comment.go b/vendor/github.com/gogs/go-gogs-client/issue_comment.go
new file mode 100644
index 0000000000..246af0d93e
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/issue_comment.go
@@ -0,0 +1,70 @@
+// Copyright 2016 The Gogs 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 gogs
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "time"
+)
+
+// Comment represents a comment in commit and issue page.
+type Comment struct {
+ ID int64 `json:"id"`
+ HTMLURL string `json:"html_url"`
+ Poster *User `json:"user"`
+ Body string `json:"body"`
+ Created time.Time `json:"created_at"`
+ Updated time.Time `json:"updated_at"`
+}
+
+// ListIssueComments list comments on an issue.
+func (c *Client) ListIssueComments(owner, repo string, index int64) ([]*Comment, error) {
+ comments := make([]*Comment, 0, 10)
+ return comments, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/comments", owner, repo, index), nil, nil, &comments)
+}
+
+// ListRepoIssueComments list comments for a given repo.
+func (c *Client) ListRepoIssueComments(owner, repo string) ([]*Comment, error) {
+ comments := make([]*Comment, 0, 10)
+ return comments, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/comments", owner, repo), nil, nil, &comments)
+}
+
+// CreateIssueCommentOption is option when creating an issue comment.
+type CreateIssueCommentOption struct {
+ Body string `json:"body" binding:"Required"`
+}
+
+// CreateIssueComment create comment on an issue.
+func (c *Client) CreateIssueComment(owner, repo string, index int64, opt CreateIssueCommentOption) (*Comment, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return 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)
+}
+
+// EditIssueCommentOption is option when editing an issue comment.
+type EditIssueCommentOption struct {
+ Body string `json:"body" binding:"Required"`
+}
+
+// EditIssueComment edits an issue comment.
+func (c *Client) EditIssueComment(owner, repo string, index, commentID int64, opt EditIssueCommentOption) (*Comment, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ comment := new(Comment)
+ return comment, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/issues/%d/comments/%d", owner, repo, index, commentID), jsonHeader, bytes.NewReader(body), comment)
+}
+
+// DeleteIssueComment deletes an issue comment.
+func (c *Client) DeleteIssueComment(owner, repo string, index, commentID int64) error {
+ _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/comments/%d", owner, repo, index, commentID), nil, nil)
+ return err
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/issue_label.go b/vendor/github.com/gogs/go-gogs-client/issue_label.go
new file mode 100644
index 0000000000..b8ff3009b4
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/issue_label.go
@@ -0,0 +1,99 @@
+// Copyright 2016 The Gogs 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 gogs
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+)
+
+type Label struct {
+ ID int64 `json:"id"`
+ Name string `json:"name"`
+ Color string `json:"color"`
+ URL string `json:"url"`
+}
+
+func (c *Client) ListRepoLabels(owner, repo string) ([]*Label, error) {
+ labels := make([]*Label, 0, 10)
+ return labels, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels", owner, repo), nil, nil, &labels)
+}
+
+func (c *Client) GetRepoLabel(owner, repo string, id int64) (*Label, error) {
+ label := new(Label)
+ return label, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil, label)
+}
+
+type CreateLabelOption struct {
+ Name string `json:"name" binding:"Required"`
+ Color string `json:"color" binding:"Required;Size(7)"`
+}
+
+func (c *Client) CreateLabel(owner, repo string, opt CreateLabelOption) (*Label, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ label := new(Label)
+ return label, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/labels", owner, repo),
+ jsonHeader, bytes.NewReader(body), label)
+}
+
+type EditLabelOption struct {
+ Name *string `json:"name"`
+ Color *string `json:"color"`
+}
+
+func (c *Client) EditLabel(owner, repo string, id int64, opt EditLabelOption) (*Label, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return 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)
+}
+
+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
+}
+
+type IssueLabelsOption struct {
+ Labels []int64 `json:"labels"`
+}
+
+func (c *Client) GetIssueLabels(owner, repo string, index int64) ([]*Label, error) {
+ labels := make([]*Label, 0, 5)
+ return labels, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), nil, nil, &labels)
+}
+
+func (c *Client) AddIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ labels := make([]*Label, 0)
+ return labels, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), jsonHeader, bytes.NewReader(body), &labels)
+}
+
+func (c *Client) ReplaceIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ labels := make([]*Label, 0)
+ return labels, c.getParsedResponse("PUT", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), jsonHeader, bytes.NewReader(body), &labels)
+}
+
+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) 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
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/issue_milestone.go b/vendor/github.com/gogs/go-gogs-client/issue_milestone.go
new file mode 100644
index 0000000000..ad27a15ef1
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/issue_milestone.go
@@ -0,0 +1,69 @@
+// Copyright 2016 The Gogs 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 gogs
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "time"
+)
+
+type Milestone struct {
+ ID int64 `json:"id"`
+ Title string `json:"title"`
+ Description string `json:"description"`
+ State StateType `json:"state"`
+ OpenIssues int `json:"open_issues"`
+ ClosedIssues int `json:"closed_issues"`
+ Closed *time.Time `json:"closed_at"`
+ Deadline *time.Time `json:"due_on"`
+}
+
+func (c *Client) ListRepoMilestones(owner, repo string) ([]*Milestone, error) {
+ milestones := make([]*Milestone, 0, 10)
+ return milestones, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones", owner, repo), nil, nil, &milestones)
+}
+
+func (c *Client) GetMilestone(owner, repo string, id int64) (*Milestone, error) {
+ milestone := new(Milestone)
+ return milestone, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil, milestone)
+}
+
+type CreateMilestoneOption struct {
+ Title string `json:"title"`
+ Description string `json:"description"`
+ Deadline *time.Time `json:"due_on"`
+}
+
+func (c *Client) CreateMilestone(owner, repo string, opt CreateMilestoneOption) (*Milestone, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ milestone := new(Milestone)
+ return milestone, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/milestones", owner, repo), jsonHeader, bytes.NewReader(body), milestone)
+}
+
+type EditMilestoneOption struct {
+ Title string `json:"title"`
+ Description *string `json:"description"`
+ State *string `json:"state"`
+ Deadline *time.Time `json:"due_on"`
+}
+
+func (c *Client) EditMilestone(owner, repo string, id int64, opt EditMilestoneOption) (*Milestone, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return 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)
+}
+
+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
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/media_types.go b/vendor/github.com/gogs/go-gogs-client/media_types.go
new file mode 100644
index 0000000000..884a8a7405
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/media_types.go
@@ -0,0 +1,9 @@
+// Copyright 2018 The Gogs 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 gogs
+
+const (
+ MediaApplicationSHA = "application/vnd.gogs.sha"
+)
diff --git a/vendor/github.com/gogs/go-gogs-client/miscellaneous.go b/vendor/github.com/gogs/go-gogs-client/miscellaneous.go
new file mode 100644
index 0000000000..c41065bf12
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/miscellaneous.go
@@ -0,0 +1,10 @@
+// Copyright 2015 The Gogs 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 gogs
+
+type MarkdownOption struct {
+ Text string
+ Context string
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/org.go b/vendor/github.com/gogs/go-gogs-client/org.go
new file mode 100644
index 0000000000..10d22b50cb
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/org.go
@@ -0,0 +1,69 @@
+// Copyright 2015 The Gogs 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 gogs
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+)
+
+type Organization struct {
+ ID int64 `json:"id"`
+ UserName string `json:"username"`
+ FullName string `json:"full_name"`
+ AvatarUrl string `json:"avatar_url"`
+ Description string `json:"description"`
+ Website string `json:"website"`
+ Location string `json:"location"`
+}
+
+func (c *Client) ListMyOrgs() ([]*Organization, error) {
+ orgs := make([]*Organization, 0, 5)
+ return orgs, c.getParsedResponse("GET", "/user/orgs", nil, nil, &orgs)
+}
+
+func (c *Client) ListUserOrgs(user string) ([]*Organization, error) {
+ orgs := make([]*Organization, 0, 5)
+ return orgs, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/orgs", user), nil, nil, &orgs)
+}
+
+func (c *Client) GetOrg(orgname string) (*Organization, error) {
+ org := new(Organization)
+ return org, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s", orgname), nil, nil, org)
+}
+
+type CreateOrgOption struct {
+ UserName string `json:"username" binding:"Required"`
+ FullName string `json:"full_name"`
+ Description string `json:"description"`
+ Website string `json:"website"`
+ Location string `json:"location"`
+}
+
+type EditOrgOption struct {
+ FullName string `json:"full_name"`
+ Description string `json:"description"`
+ Website string `json:"website"`
+ Location string `json:"location"`
+}
+
+func (c *Client) CreateOrg(opt CreateOrgOption) (*Organization, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ org := new(Organization)
+ return org, c.getParsedResponse("POST", "/user/orgs", jsonHeader, bytes.NewReader(body), org)
+}
+
+func (c *Client) EditOrg(orgname string, opt EditOrgOption) error {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return err
+ }
+ _, err = c.getResponse("PATCH", fmt.Sprintf("/orgs/%s", orgname), jsonHeader, bytes.NewReader(body))
+ return err
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/org_member.go b/vendor/github.com/gogs/go-gogs-client/org_member.go
new file mode 100644
index 0000000000..d9cdadabd8
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/org_member.go
@@ -0,0 +1,24 @@
+// Copyright 2016 The Gogs 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 gogs
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+)
+
+type AddOrgMembershipOption struct {
+ Role string `json:"role" binding:"Required"`
+}
+
+func (c *Client) AddOrgMembership(org, user string, opt AddOrgMembershipOption) error {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return err
+ }
+ _, err = c.getResponse("PUT", fmt.Sprintf("/orgs/%s/membership/%s", org, user), jsonHeader, bytes.NewReader(body))
+ return err
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/org_team.go b/vendor/github.com/gogs/go-gogs-client/org_team.go
new file mode 100644
index 0000000000..e47f6447b0
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/org_team.go
@@ -0,0 +1,25 @@
+// Copyright 2016 The Gogs 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 gogs
+
+import "fmt"
+
+type Team struct {
+ ID int64 `json:"id"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ Permission string `json:"permission"`
+}
+
+type CreateTeamOption struct {
+ Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(30)"`
+ Description string `json:"description" binding:"MaxSize(255)"`
+ Permission string `json:"permission"`
+}
+
+func (c *Client) ListTeams(name string) ([]*Team, error) {
+ teams := make([]*Team, 0, 5)
+ return teams, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/teams", name), nil, nil, &teams)
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/pull.go b/vendor/github.com/gogs/go-gogs-client/pull.go
new file mode 100644
index 0000000000..be93b269d8
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/pull.go
@@ -0,0 +1,37 @@
+// Copyright 2016 The Gogs 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 gogs
+
+import (
+ "time"
+)
+
+// PullRequest represents a pull reqesut API object.
+type PullRequest struct {
+ // Copied from issue.go
+ ID int64 `json:"id"`
+ Index int64 `json:"number"`
+ Poster *User `json:"user"`
+ Title string `json:"title"`
+ Body string `json:"body"`
+ Labels []*Label `json:"labels"`
+ Milestone *Milestone `json:"milestone"`
+ Assignee *User `json:"assignee"`
+ State StateType `json:"state"`
+ Comments int `json:"comments"`
+
+ HeadBranch string `json:"head_branch"`
+ HeadRepo *Repository `json:"head_repo"`
+ BaseBranch string `json:"base_branch"`
+ BaseRepo *Repository `json:"base_repo"`
+
+ HTMLURL string `json:"html_url"`
+
+ Mergeable *bool `json:"mergeable"`
+ HasMerged bool `json:"merged"`
+ Merged *time.Time `json:"merged_at"`
+ MergedCommitID *string `json:"merge_commit_sha"`
+ MergedBy *User `json:"merged_by"`
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/release.go b/vendor/github.com/gogs/go-gogs-client/release.go
new file mode 100644
index 0000000000..69c7f3b9ba
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/release.go
@@ -0,0 +1,22 @@
+// Copyright 2017 The Gogs 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 gogs
+
+import (
+ "time"
+)
+
+// Release represents a release API object.
+type Release struct {
+ ID int64 `json:"id"`
+ TagName string `json:"tag_name"`
+ TargetCommitish string `json:"target_commitish"`
+ Name string `json:"name"`
+ Body string `json:"body"`
+ Draft bool `json:"draft"`
+ Prerelease bool `json:"prerelease"`
+ Author *User `json:"author"`
+ Created time.Time `json:"created_at"`
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/repo.go b/vendor/github.com/gogs/go-gogs-client/repo.go
new file mode 100644
index 0000000000..b31cd09faa
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/repo.go
@@ -0,0 +1,172 @@
+// Copyright 2014 The Gogs 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 gogs
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "time"
+)
+
+// Permission represents a API permission.
+type Permission struct {
+ Admin bool `json:"admin"`
+ Push bool `json:"push"`
+ Pull bool `json:"pull"`
+}
+
+// Repository represents a API 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"`
+ Private bool `json:"private"`
+ Unlisted bool `json:"unlisted"`
+ Fork bool `json:"fork"`
+ Parent *Repository `json:"parent"`
+ Empty bool `json:"empty"`
+ Mirror bool `json:"mirror"`
+ Size int64 `json:"size"`
+ HTMLURL string `json:"html_url"`
+ SSHURL string `json:"ssh_url"`
+ CloneURL string `json:"clone_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"`
+ Created time.Time `json:"created_at"`
+ Updated time.Time `json:"updated_at"`
+ Permissions *Permission `json:"permissions,omitempty"`
+}
+
+// ListMyRepos lists all repositories for the authenticated user that has access to.
+func (c *Client) ListMyRepos() ([]*Repository, error) {
+ repos := make([]*Repository, 0, 10)
+ return repos, c.getParsedResponse("GET", "/user/repos", nil, nil, &repos)
+}
+
+func (c *Client) ListUserRepos(user string) ([]*Repository, error) {
+ repos := make([]*Repository, 0, 10)
+ return repos, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/repos", user), nil, nil, &repos)
+}
+
+func (c *Client) ListOrgRepos(org string) ([]*Repository, error) {
+ repos := make([]*Repository, 0, 10)
+ return repos, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/repos", org), nil, nil, &repos)
+}
+
+type CreateRepoOption struct {
+ Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(100)"`
+ Description string `json:"description" binding:"MaxSize(255)"`
+ Private bool `json:"private"`
+ Unlisted bool `json:"unlisted"`
+ AutoInit bool `json:"auto_init"`
+ Gitignores string `json:"gitignores"`
+ License string `json:"license"`
+ Readme string `json:"readme"`
+}
+
+// CreateRepo creates a repository for authenticated user.
+func (c *Client) CreateRepo(opt CreateRepoOption) (*Repository, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ repo := new(Repository)
+ return repo, c.getParsedResponse("POST", "/user/repos", jsonHeader, bytes.NewReader(body), repo)
+}
+
+// CreateOrgRepo creates an organization repository for authenticated user.
+func (c *Client) CreateOrgRepo(org string, opt CreateRepoOption) (*Repository, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ repo := new(Repository)
+ return repo, c.getParsedResponse("POST", fmt.Sprintf("/org/%s/repos", org), jsonHeader, bytes.NewReader(body), repo)
+}
+
+// GetRepo returns information of a repository of given owner.
+func (c *Client) GetRepo(owner, reponame string) (*Repository, error) {
+ repo := new(Repository)
+ return repo, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s", owner, reponame), nil, nil, repo)
+}
+
+// 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
+}
+
+type MigrateRepoOption struct {
+ CloneAddr string `json:"clone_addr" binding:"Required"`
+ AuthUsername string `json:"auth_username"`
+ AuthPassword string `json:"auth_password"`
+ UID int `json:"uid" binding:"Required"`
+ RepoName string `json:"repo_name" binding:"Required"`
+ Mirror bool `json:"mirror"`
+ Private bool `json:"private"`
+ Unlisted bool `json:"unlisted"`
+ Description string `json:"description"`
+}
+
+// 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)
+ if err != nil {
+ return nil, err
+ }
+ repo := new(Repository)
+ return repo, c.getParsedResponse("POST", "/repos/migrate", jsonHeader, bytes.NewReader(body), repo)
+}
+
+type EditIssueTrackerOption struct {
+ EnableIssues *bool `json:"enable_issues"`
+ EnableExternalTracker *bool `json:"enable_external_tracker"`
+ ExternalTrackerURL *string `json:"external_tracker_url"`
+ TrackerURLFormat *string `json:"tracker_url_format"`
+ TrackerIssueStyle *string `json:"tracker_issue_style"`
+}
+
+// EditIssueTracker updates issue tracker options of the repository.
+func (c *Client) EditIssueTracker(owner, repo string, opt EditIssueTrackerOption) error {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return err
+ }
+ _, err = c.getResponse("PATCH", fmt.Sprintf("/repos/%s/%s/issue-tracker", owner, repo), jsonHeader, bytes.NewReader(body))
+ return err
+}
+
+type EditWikiOption struct {
+ EnableWiki *bool `json:"enable_wiki"`
+ AllowPublicWiki *bool `json:"allow_public_wiki"`
+ EnableExternalWiki *bool `json:"enable_external_wiki"`
+ ExternalWikiURL *string `json:"external_wiki_url"`
+}
+
+// EditWiki updates wiki options of the repository.
+func (c *Client) EditWiki(owner, repo string, opt EditWikiOption) error {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return err
+ }
+ _, err = c.getResponse("PATCH", fmt.Sprintf("/repos/%s/%s/wiki", owner, repo), jsonHeader, bytes.NewReader(body))
+ return err
+}
+
+func (c *Client) MirrorSync(owner, repo string) error {
+ _, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/mirror-sync", owner, repo), jsonHeader, nil)
+ return err
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/repo_branch.go b/vendor/github.com/gogs/go-gogs-client/repo_branch.go
new file mode 100644
index 0000000000..1e5811212c
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/repo_branch.go
@@ -0,0 +1,25 @@
+// Copyright 2016 The Gogs 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 gogs
+
+import (
+ "fmt"
+)
+
+// Branch represents a repository branch.
+type Branch struct {
+ Name string `json:"name"`
+ Commit *PayloadCommit `json:"commit"`
+}
+
+func (c *Client) ListRepoBranches(user, repo string) ([]*Branch, error) {
+ branches := make([]*Branch, 0, 10)
+ return branches, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches", user, repo), nil, nil, &branches)
+}
+
+func (c *Client) GetRepoBranch(user, repo, branch string) (*Branch, error) {
+ b := new(Branch)
+ return b, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil, &b)
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/repo_collaborator.go b/vendor/github.com/gogs/go-gogs-client/repo_collaborator.go
new file mode 100644
index 0000000000..6030850e6a
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/repo_collaborator.go
@@ -0,0 +1,44 @@
+// Copyright 2016 The Gogs 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 gogs
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+)
+
+type Collaborator struct {
+ *User
+ Permissions Permission `json:"permissions"`
+}
+
+type AddCollaboratorOption struct {
+ Permission *string `json:"permission"`
+}
+
+func (c *Client) ListCollaborator(user, repo string) ([]*Collaborator, error) {
+ collabs := make([]*Collaborator, 0, 10)
+ return collabs, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/collaborators", user, repo), nil, nil, &collabs)
+}
+
+func (c *Client) AddCollaborator(user, repo, collaborator string, opt AddCollaboratorOption) error {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return err
+ }
+ _, err = c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), jsonHeader, bytes.NewReader(body))
+ return err
+}
+
+func (c *Client) DeleteCollaborator(user, repo, collaborator string) error {
+ _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), nil, nil)
+ return err
+}
+
+func (c *Client) IsCollaborator(user, repo, collaborator string) error {
+ _, err := c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), nil, nil)
+ return err
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/repo_commit.go b/vendor/github.com/gogs/go-gogs-client/repo_commit.go
new file mode 100644
index 0000000000..b415962a2e
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/repo_commit.go
@@ -0,0 +1,53 @@
+// Copyright 2018 The Gogs 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 gogs
+
+import (
+ "fmt"
+ "net/http"
+)
+
+// CommitMeta contains meta information of a commit in terms of API.
+type CommitMeta struct {
+ URL string `json:"url"`
+ SHA string `json:"sha"`
+}
+
+// CommitUser contains information of a user in the context of a commit.
+type CommitUser struct {
+ Name string `json:"name"`
+ Email string `json:"email"`
+ Date string `json:"date"`
+}
+
+// RepoCommit contains information of a commit in the context of a repository.
+type RepoCommit struct {
+ URL string `json:"url"`
+ Author *CommitUser `json:"author"`
+ Committer *CommitUser `json:"committer"`
+ Message string `json:"message"`
+ Tree *CommitMeta `json:"tree"`
+}
+
+// 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"`
+}
+
+func (c *Client) GetSingleCommit(user, repo, commitID string) (*Commit, error) {
+ commit := new(Commit)
+ return commit, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s", user, repo, commitID), nil, nil, &commit)
+}
+
+func (c *Client) GetReferenceSHA(user, repo, ref string) (string, error) {
+ data, err := c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s", user, repo, ref),
+ http.Header{"Accept": []string{MediaApplicationSHA}}, nil)
+ return string(data), err
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/repo_file.go b/vendor/github.com/gogs/go-gogs-client/repo_file.go
new file mode 100644
index 0000000000..d766fb6d8a
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/repo_file.go
@@ -0,0 +1,23 @@
+// Copyright 2014 The Gogs 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 gogs
+
+import (
+ "fmt"
+)
+
+// 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)
+}
+
+// GetArchive downloads the full contents of a repository. Ref can be a branch/tag/commit.
+func (c *Client) GetArchive(user, repo, ref, format string) ([]byte, error) {
+ if format != ".zip" && format != ".tar.gz" {
+ return nil, fmt.Errorf("invalid format: %s (must be .zip or .tar.gz)", format)
+ }
+ return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/archive/%s%s", user, repo, ref, format), nil, nil)
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/repo_hook.go b/vendor/github.com/gogs/go-gogs-client/repo_hook.go
new file mode 100644
index 0000000000..8896b4263e
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/repo_hook.go
@@ -0,0 +1,345 @@
+// Copyright 2014 The Gogs 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 gogs
+
+import (
+ "bytes"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+)
+
+var (
+ ErrInvalidReceiveHook = errors.New("invalid JSON payload received over webhook")
+)
+
+type Hook struct {
+ ID int64 `json:"id"`
+ Type string `json:"type"`
+ URL string `json:"-"`
+ Config map[string]string `json:"config"`
+ Events []string `json:"events"`
+ Active bool `json:"active"`
+ Updated time.Time `json:"updated_at"`
+ Created time.Time `json:"created_at"`
+}
+
+func (c *Client) ListRepoHooks(user, repo string) ([]*Hook, error) {
+ hooks := make([]*Hook, 0, 10)
+ return hooks, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks", user, repo), nil, nil, &hooks)
+}
+
+type CreateHookOption struct {
+ Type string `json:"type" binding:"Required"`
+ Config map[string]string `json:"config" binding:"Required"`
+ Events []string `json:"events"`
+ Active bool `json:"active"`
+}
+
+func (c *Client) CreateRepoHook(user, repo string, opt CreateHookOption) (*Hook, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ h := new(Hook)
+ return h, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/hooks", user, repo), jsonHeader, bytes.NewReader(body), h)
+}
+
+type EditHookOption struct {
+ Config map[string]string `json:"config"`
+ Events []string `json:"events"`
+ Active *bool `json:"active"`
+}
+
+func (c *Client) EditRepoHook(user, repo string, id int64, opt EditHookOption) error {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return err
+ }
+ _, err = c.getResponse("PATCH", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), jsonHeader, bytes.NewReader(body))
+ return err
+}
+
+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
+}
+
+type Payloader interface {
+ JSONPayload() ([]byte, error)
+}
+
+type PayloadUser struct {
+ Name string `json:"name"`
+ Email string `json:"email"`
+ UserName string `json:"username"`
+}
+
+// FIXME: consider use same format as API when commits API are added.
+type PayloadCommit struct {
+ ID string `json:"id"`
+ Message string `json:"message"`
+ URL string `json:"url"`
+ Author *PayloadUser `json:"author"`
+ Committer *PayloadUser `json:"committer"`
+
+ Added []string `json:"added"`
+ Removed []string `json:"removed"`
+ Modified []string `json:"modified"`
+
+ Timestamp time.Time `json:"timestamp"`
+}
+
+var (
+ _ Payloader = &CreatePayload{}
+ _ Payloader = &DeletePayload{}
+ _ Payloader = &ForkPayload{}
+ _ Payloader = &PushPayload{}
+ _ Payloader = &IssuesPayload{}
+ _ Payloader = &IssueCommentPayload{}
+ _ Payloader = &PullRequestPayload{}
+)
+
+// _________ __
+// \_ ___ \_______ ____ _____ _/ |_ ____
+// / \ \/\_ __ \_/ __ \\__ \\ __\/ __ \
+// \ \____| | \/\ ___/ / __ \| | \ ___/
+// \______ /|__| \___ >____ /__| \___ >
+// \/ \/ \/ \/
+
+type CreatePayload struct {
+ Ref string `json:"ref"`
+ RefType string `json:"ref_type"`
+ Sha string `json:"sha"`
+ DefaultBranch string `json:"default_branch"`
+ Repo *Repository `json:"repository"`
+ Sender *User `json:"sender"`
+}
+
+func (p *CreatePayload) JSONPayload() ([]byte, error) {
+ return json.MarshalIndent(p, "", " ")
+}
+
+// ParseCreateHook parses create event hook content.
+func ParseCreateHook(raw []byte) (*CreatePayload, error) {
+ hook := new(CreatePayload)
+ if err := json.Unmarshal(raw, hook); err != nil {
+ return nil, err
+ }
+
+ // it is possible the JSON was parsed, however,
+ // was not from Gogs (maybe was from Bitbucket)
+ // So we'll check to be sure certain key fields
+ // were populated
+ switch {
+ case hook.Repo == nil:
+ return nil, ErrInvalidReceiveHook
+ case len(hook.Ref) == 0:
+ return nil, ErrInvalidReceiveHook
+ }
+ return hook, nil
+}
+
+// ________ .__ __
+// \______ \ ____ | | _____/ |_ ____
+// | | \_/ __ \| | _/ __ \ __\/ __ \
+// | ` \ ___/| |_\ ___/| | \ ___/
+// /_______ /\___ >____/\___ >__| \___ >
+// \/ \/ \/ \/
+
+type PusherType string
+
+const (
+ PUSHER_TYPE_USER PusherType = "user"
+)
+
+type DeletePayload struct {
+ Ref string `json:"ref"`
+ RefType string `json:"ref_type"`
+ PusherType PusherType `json:"pusher_type"`
+ Repo *Repository `json:"repository"`
+ Sender *User `json:"sender"`
+}
+
+func (p *DeletePayload) JSONPayload() ([]byte, error) {
+ return json.MarshalIndent(p, "", " ")
+}
+
+// ___________ __
+// \_ _____/__________| | __
+// | __)/ _ \_ __ \ |/ /
+// | \( <_> ) | \/ <
+// \___ / \____/|__| |__|_ \
+// \/ \/
+
+type ForkPayload struct {
+ Forkee *Repository `json:"forkee"`
+ Repo *Repository `json:"repository"`
+ Sender *User `json:"sender"`
+}
+
+func (p *ForkPayload) JSONPayload() ([]byte, error) {
+ return json.MarshalIndent(p, "", " ")
+}
+
+// __________ .__
+// \______ \__ __ _____| |__
+// | ___/ | \/ ___/ | \
+// | | | | /\___ \| Y \
+// |____| |____//____ >___| /
+// \/ \/
+
+// PushPayload represents a payload information of push event.
+type PushPayload struct {
+ Ref string `json:"ref"`
+ Before string `json:"before"`
+ After string `json:"after"`
+ CompareURL string `json:"compare_url"`
+ Commits []*PayloadCommit `json:"commits"`
+ Repo *Repository `json:"repository"`
+ Pusher *User `json:"pusher"`
+ Sender *User `json:"sender"`
+}
+
+func (p *PushPayload) JSONPayload() ([]byte, error) {
+ return json.MarshalIndent(p, "", " ")
+}
+
+// ParsePushHook parses push event hook content.
+func ParsePushHook(raw []byte) (*PushPayload, error) {
+ hook := new(PushPayload)
+ if err := json.Unmarshal(raw, hook); err != nil {
+ return nil, err
+ }
+
+ switch {
+ case hook.Repo == nil:
+ return nil, ErrInvalidReceiveHook
+ case len(hook.Ref) == 0:
+ return nil, ErrInvalidReceiveHook
+ }
+ return hook, nil
+}
+
+// Branch returns branch name from a payload
+func (p *PushPayload) Branch() string {
+ return strings.Replace(p.Ref, "refs/heads/", "", -1)
+}
+
+// .___
+// | | ______ ________ __ ____
+// | |/ ___// ___/ | \_/ __ \
+// | |\___ \ \___ \| | /\ ___/
+// |___/____ >____ >____/ \___ >
+// \/ \/ \/
+
+type HookIssueAction string
+
+const (
+ HOOK_ISSUE_OPENED HookIssueAction = "opened"
+ HOOK_ISSUE_CLOSED HookIssueAction = "closed"
+ HOOK_ISSUE_REOPENED HookIssueAction = "reopened"
+ HOOK_ISSUE_EDITED HookIssueAction = "edited"
+ HOOK_ISSUE_ASSIGNED HookIssueAction = "assigned"
+ HOOK_ISSUE_UNASSIGNED HookIssueAction = "unassigned"
+ HOOK_ISSUE_LABEL_UPDATED HookIssueAction = "label_updated"
+ HOOK_ISSUE_LABEL_CLEARED HookIssueAction = "label_cleared"
+ HOOK_ISSUE_MILESTONED HookIssueAction = "milestoned"
+ HOOK_ISSUE_DEMILESTONED HookIssueAction = "demilestoned"
+ HOOK_ISSUE_SYNCHRONIZED HookIssueAction = "synchronized"
+)
+
+type ChangesFromPayload struct {
+ From string `json:"from"`
+}
+
+type ChangesPayload struct {
+ Title *ChangesFromPayload `json:"title,omitempty"`
+ Body *ChangesFromPayload `json:"body,omitempty"`
+}
+
+// IssuesPayload represents a payload information of issues event.
+type IssuesPayload struct {
+ Action HookIssueAction `json:"action"`
+ Index int64 `json:"number"`
+ Issue *Issue `json:"issue"`
+ Changes *ChangesPayload `json:"changes,omitempty"`
+ Repository *Repository `json:"repository"`
+ Sender *User `json:"sender"`
+}
+
+func (p *IssuesPayload) JSONPayload() ([]byte, error) {
+ return json.MarshalIndent(p, "", " ")
+}
+
+type HookIssueCommentAction string
+
+const (
+ HOOK_ISSUE_COMMENT_CREATED HookIssueCommentAction = "created"
+ HOOK_ISSUE_COMMENT_EDITED HookIssueCommentAction = "edited"
+ HOOK_ISSUE_COMMENT_DELETED HookIssueCommentAction = "deleted"
+)
+
+// IssueCommentPayload represents a payload information of issue comment event.
+type IssueCommentPayload struct {
+ Action HookIssueCommentAction `json:"action"`
+ Issue *Issue `json:"issue"`
+ Comment *Comment `json:"comment"`
+ Changes *ChangesPayload `json:"changes,omitempty"`
+ Repository *Repository `json:"repository"`
+ Sender *User `json:"sender"`
+}
+
+func (p *IssueCommentPayload) JSONPayload() ([]byte, error) {
+ return json.MarshalIndent(p, "", " ")
+}
+
+// __________ .__ .__ __________ __
+// \______ \__ __| | | | \______ \ ____ ________ __ ____ _______/ |_
+// | ___/ | \ | | | | _// __ \/ ____/ | \_/ __ \ / ___/\ __\
+// | | | | / |_| |__ | | \ ___< <_| | | /\ ___/ \___ \ | |
+// |____| |____/|____/____/ |____|_ /\___ >__ |____/ \___ >____ > |__|
+// \/ \/ |__| \/ \/
+
+// PullRequestPayload represents a payload information of pull request event.
+type PullRequestPayload struct {
+ Action HookIssueAction `json:"action"`
+ Index int64 `json:"number"`
+ PullRequest *PullRequest `json:"pull_request"`
+ Changes *ChangesPayload `json:"changes,omitempty"`
+ Repository *Repository `json:"repository"`
+ Sender *User `json:"sender"`
+}
+
+func (p *PullRequestPayload) JSONPayload() ([]byte, error) {
+ return json.MarshalIndent(p, "", " ")
+}
+
+// __________ .__
+// \______ \ ____ | | ____ _____ ______ ____
+// | _// __ \| | _/ __ \\__ \ / ___// __ \
+// | | \ ___/| |_\ ___/ / __ \_\___ \\ ___/
+// |____|_ /\___ >____/\___ >____ /____ >\___ >
+// \/ \/ \/ \/ \/ \/
+
+type HookReleaseAction string
+
+const (
+ HOOK_RELEASE_PUBLISHED HookReleaseAction = "published"
+)
+
+// ReleasePayload represents a payload information of release event.
+type ReleasePayload struct {
+ Action HookReleaseAction `json:"action"`
+ Release *Release `json:"release"`
+ Repository *Repository `json:"repository"`
+ Sender *User `json:"sender"`
+}
+
+func (p *ReleasePayload) JSONPayload() ([]byte, error) {
+ return json.MarshalIndent(p, "", " ")
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/repo_key.go b/vendor/github.com/gogs/go-gogs-client/repo_key.go
new file mode 100644
index 0000000000..2201602c1f
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/repo_key.go
@@ -0,0 +1,50 @@
+// Copyright 2015 The Gogs 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 gogs
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "time"
+)
+
+type DeployKey struct {
+ ID int64 `json:"id"`
+ Key string `json:"key"`
+ URL string `json:"url"`
+ Title string `json:"title"`
+ Created time.Time `json:"created_at"`
+ ReadOnly bool `json:"read_only"`
+}
+
+func (c *Client) ListDeployKeys(user, repo string) ([]*DeployKey, error) {
+ keys := make([]*DeployKey, 0, 10)
+ return keys, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/keys", user, repo), nil, nil, &keys)
+}
+
+func (c *Client) GetDeployKey(user, repo string, keyID int64) (*DeployKey, error) {
+ key := new(DeployKey)
+ return key, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/keys/%d", user, repo, keyID), nil, nil, &key)
+}
+
+type CreateKeyOption struct {
+ Title string `json:"title" binding:"Required"`
+ Key string `json:"key" binding:"Required"`
+}
+
+func (c *Client) CreateDeployKey(user, repo string, opt CreateKeyOption) (*DeployKey, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ key := new(DeployKey)
+ return key, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/keys", user, repo), jsonHeader, bytes.NewReader(body), key)
+}
+
+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
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/user.go b/vendor/github.com/gogs/go-gogs-client/user.go
new file mode 100644
index 0000000000..2b5da092c6
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/user.go
@@ -0,0 +1,31 @@
+// Copyright 2014 The Gogs 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 gogs
+
+import (
+ "fmt"
+)
+
+// User represents a API user.
+type User struct {
+ ID int64 `json:"id"`
+ UserName string `json:"username"` // LEGACY [Gogs 1.0]: remove field(s) for backward compatibility
+ Login string `json:"login"`
+ FullName string `json:"full_name"`
+ Email string `json:"email"`
+ AvatarUrl string `json:"avatar_url"`
+}
+
+func (c *Client) GetUserInfo(user string) (*User, error) {
+ u := new(User)
+ err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s", user), nil, nil, u)
+ return u, err
+}
+
+func (c *Client) GetSelfInfo() (*User, error) {
+ u := new(User)
+ err := c.getParsedResponse("GET", "/user", nil, nil, u)
+ return u, err
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/user_app.go b/vendor/github.com/gogs/go-gogs-client/user_app.go
new file mode 100644
index 0000000000..965ed6ebfd
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/user_app.go
@@ -0,0 +1,46 @@
+// Copyright 2014 The Gogs 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 gogs
+
+import (
+ "bytes"
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "net/http"
+)
+
+func BasicAuthEncode(user, pass string) string {
+ return base64.StdEncoding.EncodeToString([]byte(user + ":" + pass))
+}
+
+// AccessToken represents a API access token.
+type AccessToken struct {
+ Name string `json:"name"`
+ Sha1 string `json:"sha1"`
+}
+
+func (c *Client) ListAccessTokens(user, pass string) ([]*AccessToken, error) {
+ tokens := make([]*AccessToken, 0, 10)
+ return tokens, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/tokens", user),
+ http.Header{"Authorization": []string{"Basic " + BasicAuthEncode(user, pass)}}, nil, &tokens)
+}
+
+type CreateAccessTokenOption struct {
+ Name string `json:"name" binding:"Required"`
+}
+
+func (c *Client) CreateAccessToken(user, pass string, opt CreateAccessTokenOption) (*AccessToken, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ t := new(AccessToken)
+ return t, c.getParsedResponse("POST", fmt.Sprintf("/users/%s/tokens", user),
+ http.Header{
+ "content-type": []string{"application/json"},
+ "Authorization": []string{"Basic " + BasicAuthEncode(user, pass)}},
+ bytes.NewReader(body), t)
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/user_email.go b/vendor/github.com/gogs/go-gogs-client/user_email.go
new file mode 100644
index 0000000000..02dd402315
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/user_email.go
@@ -0,0 +1,43 @@
+// Copyright 2015 The Gogs 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 gogs
+
+import (
+ "bytes"
+ "encoding/json"
+)
+
+type Email struct {
+ Email string `json:"email"`
+ Verified bool `json:"verified"`
+ Primary bool `json:"primary"`
+}
+
+func (c *Client) ListEmails() ([]*Email, error) {
+ emails := make([]*Email, 0, 3)
+ return emails, c.getParsedResponse("GET", "/user/emails", nil, nil, &emails)
+}
+
+type CreateEmailOption struct {
+ Emails []string `json:"emails"`
+}
+
+func (c *Client) AddEmail(opt CreateEmailOption) ([]*Email, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ emails := make([]*Email, 0, 3)
+ return emails, c.getParsedResponse("POST", "/user/emails", jsonHeader, bytes.NewReader(body), emails)
+}
+
+func (c *Client) DeleteEmail(opt CreateEmailOption) error {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return err
+ }
+ _, err = c.getResponse("DELETE", "/user/emails", jsonHeader, bytes.NewReader(body))
+ return err
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/user_follow.go b/vendor/github.com/gogs/go-gogs-client/user_follow.go
new file mode 100644
index 0000000000..5ba20cc084
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/user_follow.go
@@ -0,0 +1,47 @@
+// Copyright 2015 The Gogs 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 gogs
+
+import "fmt"
+
+func (c *Client) ListMyFollowers(page int) ([]*User, error) {
+ users := make([]*User, 0, 10)
+ return users, c.getParsedResponse("GET", fmt.Sprintf("/user/followers?page=%d", page), nil, nil, &users)
+}
+
+func (c *Client) ListFollowers(user string, page int) ([]*User, error) {
+ users := make([]*User, 0, 10)
+ return users, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/followers?page=%d", user, page), nil, nil, &users)
+}
+
+func (c *Client) ListMyFollowing(page int) ([]*User, error) {
+ users := make([]*User, 0, 10)
+ return users, c.getParsedResponse("GET", fmt.Sprintf("/user/following?page=%d", page), nil, nil, &users)
+}
+
+func (c *Client) ListFollowing(user string, page int) ([]*User, error) {
+ users := make([]*User, 0, 10)
+ return users, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/following?page=%d", user, page), nil, nil, &users)
+}
+
+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) 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) Follow(target string) error {
+ _, err := c.getResponse("PUT", fmt.Sprintf("/user/following/%s", target), jsonHeader, nil)
+ return err
+}
+
+func (c *Client) Unfollow(target string) error {
+ _, err := c.getResponse("DELETE", fmt.Sprintf("/user/following/%s", target), nil, nil)
+ return err
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/user_key.go b/vendor/github.com/gogs/go-gogs-client/user_key.go
new file mode 100644
index 0000000000..c0278e0e9c
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/user_key.go
@@ -0,0 +1,49 @@
+// Copyright 2015 The Gogs 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 gogs
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "time"
+)
+
+type PublicKey struct {
+ ID int64 `json:"id"`
+ Key string `json:"key"`
+ URL string `json:"url,omitempty"`
+ Title string `json:"title,omitempty"`
+ Created time.Time `json:"created_at,omitempty"`
+}
+
+func (c *Client) ListPublicKeys(user string) ([]*PublicKey, error) {
+ keys := make([]*PublicKey, 0, 10)
+ return keys, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/keys", user), nil, nil, &keys)
+}
+
+func (c *Client) ListMyPublicKeys() ([]*PublicKey, error) {
+ keys := make([]*PublicKey, 0, 10)
+ return keys, c.getParsedResponse("GET", "/user/keys", nil, nil, &keys)
+}
+
+func (c *Client) GetPublicKey(keyID int64) (*PublicKey, error) {
+ key := new(PublicKey)
+ return key, c.getParsedResponse("GET", fmt.Sprintf("/user/keys/%d", keyID), nil, nil, &key)
+}
+
+func (c *Client) CreatePublicKey(opt CreateKeyOption) (*PublicKey, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ key := new(PublicKey)
+ return key, c.getParsedResponse("POST", "/user/keys", jsonHeader, bytes.NewReader(body), key)
+}
+
+func (c *Client) DeletePublicKey(keyID int64) error {
+ _, err := c.getResponse("DELETE", fmt.Sprintf("/user/keys/%d", keyID), nil, nil)
+ return err
+}
diff --git a/vendor/github.com/gogs/go-gogs-client/utils.go b/vendor/github.com/gogs/go-gogs-client/utils.go
new file mode 100644
index 0000000000..a4d673e0f7
--- /dev/null
+++ b/vendor/github.com/gogs/go-gogs-client/utils.go
@@ -0,0 +1,23 @@
+// Copyright 2015 The Gogs 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 gogs
+
+import (
+ "net/http"
+)
+
+var jsonHeader = http.Header{"content-type": []string{"application/json"}}
+
+func Bool(v bool) *bool {
+ return &v
+}
+
+func String(v string) *string {
+ return &v
+}
+
+func Int64(v int64) *int64 {
+ return &v
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index cc200bb50b..7cc923850f 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -415,6 +415,9 @@ github.com/gogs/chardet
# github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
## explicit
github.com/gogs/cron
+# github.com/gogs/go-gogs-client v0.0.0-20200905025246-8bb8a50cb355 => github.com/6543-forks/go-gogs-client v0.0.0-20210116182316-f2f8bc0ea9cc
+## explicit
+github.com/gogs/go-gogs-client
# github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe
github.com/golang-sql/civil
# github.com/golang/protobuf v1.4.3
@@ -1009,3 +1012,4 @@ xorm.io/xorm/schemas
xorm.io/xorm/tags
# github.com/hashicorp/go-version => github.com/6543/go-version v1.2.4
# github.com/microcosm-cc/bluemonday => github.com/lunny/bluemonday v1.0.5-0.20201227154428-ca34796141e8
+# github.com/gogs/go-gogs-client => github.com/6543-forks/go-gogs-client v0.0.0-20210116182316-f2f8bc0ea9cc
diff --git a/web_src/svg/gitea-gogs.svg b/web_src/svg/gitea-gogs.svg
new file mode 100644
index 0000000000..b1ff153b94
--- /dev/null
+++ b/web_src/svg/gitea-gogs.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" width="64" height="64"><path d="M250.368 634.375c-1.445-1.719-5.882-14.218-9.861-27.776-6.693-22.806-7.834-24.852-15.253-27.32-18.366-6.114-58.769-27.528-76.961-40.792l-19.513-14.226-13.658 2.87c-7.512 1.578-19.901 4.187-27.532 5.797-7.63 1.61-15.629 2.28-17.775 1.49-5.153-1.9-67.213-105.858-67.213-112.59 0-3.117 7.884-13.005 19.58-24.553l19.579-19.334-2.019-10.845c-2.575-13.836-2.626-77.041-.075-93.016l1.944-12.17-19.505-19.26C11.38 232.059 2.602 221.277 2.602 218.692c0-5.203 57.532-102.157 65.08-109.674 4.66-4.64 5.296-4.602 32.6 1.972 23.225 5.593 28.603 6.17 32.394 3.483 2.5-1.772 11.192-8.08 19.316-14.017 17.467-12.767 46.373-28.038 67.035-35.415 16.18-5.777 14.574-3.303 25.386-39.125 2.961-9.81 6.983-19.11 8.937-20.669 2.492-1.987 23.264-2.634 69.573-2.165l66.02.669 7.263 22.5c10.553 32.692 10.945 33.186 32.986 41.62 22.359 8.557 43.687 20.45 67.505 37.646 9.302 6.716 18.52 11.54 20.813 10.892 22.045-6.226 48.383-11.336 52.287-10.146 4.188 1.278 69.76 109.778 70.033 112.359.013.12.079.517-.02.736-1.145 2.52-9.555 11.185-19.532 21.501l-19.721 20.392 2.16 20c2.747 25.424 2.753 54.731.019 79.072l-2.144 19.072 19.705 20.247c10.837 11.136 18.425 17.638 19.39 23.528 1.26 7.694-59.597 102.142-64.49 107.807-4.608 5.336-10.065 5.135-38.606-1.427l-24.061-5.531-7.159 5.454c-20.202 15.39-52.104 34.238-71.37 42.165-11.903 4.898-22.998 10.19-24.655 11.759-1.657 1.57-5.568 11.854-8.691 22.854-9.693 34.139-2.26 31.25-80.395 31.25-50.676 0-67.912-.77-69.89-3.125zm142.478-129.169c43.26-14.006 81.273-41.624 104.19-75.696 12.313-18.306 13.493-29.43 4.006-37.754-3.452-3.028-28.33-17.778-55.285-32.776-26.955-14.999-49.87-28.499-50.92-30-1.052-1.502-1.93-7.29-1.952-12.864-.081-20.804-17.326-43.277-40.282-52.494-12.372-4.967-34.32-4.466-47.013 1.074-20.895 9.12-37.623 33.977-37.623 55.905 0 21.402 16.363 45.103 37.724 54.642 13.858 6.188 35.787 6.059 50.365-.298 6.238-2.72 12.836-4.945 14.663-4.945 5.463 0 77.218 40.737 78.82 44.749 2.349 5.88-26.722 29.365-50.16 40.522-92.78 44.165-201.16-8.158-221.452-106.91-5.11-24.87-3.26-49.806 5.569-75.08 8.57-24.532 17.004-38.117 35.291-56.841 45.768-46.862 118.154-59.479 180.51-31.463 20.447 9.186 24.754 9.315 34.975 1.05 6.357-5.14 8.004-8.43 8.004-15.99 0-12.71-11.123-22.053-38.15-32.046-49.005-18.119-103.977-17.624-150.994 1.358-59.09 23.858-106.171 78.297-119.34 137.993-4.86 22.031-4.667 63.731.398 85.914 2.26 9.897 9.98 29.702 17.157 44.013 11.422 22.775 16.017 28.883 36.867 49.007 43.93 42.4 87.826 59.46 148.697 57.79 26.8-.736 34.718-1.99 55.935-8.86z" fill="#d4553b"/></svg>