mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 08:02:36 +09:00 
			
		
		
		
	Compare commits
	
		
			56 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					55e159ca5f | ||
| 
						 | 
					87074ec860 | ||
| 
						 | 
					1fe5fe419e | ||
| 
						 | 
					67a12b8fac | ||
| 
						 | 
					e861dcbbaf | ||
| 
						 | 
					53c2136a9a | ||
| 
						 | 
					24ebc7e517 | ||
| 
						 | 
					b072907987 | ||
| 
						 | 
					942b0360ad | ||
| 
						 | 
					1ec4913add | ||
| 
						 | 
					16e34025b4 | ||
| 
						 | 
					456d63b6cf | ||
| 
						 | 
					798ac3f85a | ||
| 
						 | 
					460093b952 | ||
| 
						 | 
					38d184d518 | ||
| 
						 | 
					80b55263d8 | ||
| 
						 | 
					32232db55f | ||
| 
						 | 
					cf9b6c281f | ||
| 
						 | 
					a8c6a4a70e | ||
| 
						 | 
					e6050e80f7 | ||
| 
						 | 
					3803b15d76 | ||
| 
						 | 
					af73e1ee35 | ||
| 
						 | 
					4bc8dfc6a3 | ||
| 
						 | 
					33c4e246fe | ||
| 
						 | 
					8ec7beb9f4 | ||
| 
						 | 
					c6eb9b30ae | ||
| 
						 | 
					f75a9b27b0 | ||
| 
						 | 
					2705696d4d | ||
| 
						 | 
					2b68f66e0e | ||
| 
						 | 
					5c7d30cf52 | ||
| 
						 | 
					e520dff4da | ||
| 
						 | 
					2bc759518e | ||
| 
						 | 
					92b2883058 | ||
| 
						 | 
					0ebfc1405c | ||
| 
						 | 
					fd5c67226e | ||
| 
						 | 
					61308825a6 | ||
| 
						 | 
					0cccad04f0 | ||
| 
						 | 
					a0e5c49ac3 | ||
| 
						 | 
					3558310c1f | ||
| 
						 | 
					e99534cfd2 | ||
| 
						 | 
					27acf6165e | ||
| 
						 | 
					f286a28568 | ||
| 
						 | 
					b5c4cb1bde | ||
| 
						 | 
					26b98417ad | ||
| 
						 | 
					8b0cf88c0c | ||
| 
						 | 
					23db3375df | ||
| 
						 | 
					14011d77c9 | ||
| 
						 | 
					5519e26c2f | ||
| 
						 | 
					6feb435867 | ||
| 
						 | 
					61444ed8ca | ||
| 
						 | 
					d770cc9886 | ||
| 
						 | 
					fbaa01998a | ||
| 
						 | 
					ac2ae66ae7 | ||
| 
						 | 
					ed60fe0986 | ||
| 
						 | 
					29e0d62790 | ||
| 
						 | 
					7b464fa67b | 
							
								
								
									
										70
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -4,14 +4,16 @@ This changelog goes through all the changes that have been made in each release
 | 
			
		||||
without substantial changes to our git log; to see the highlights of what has
 | 
			
		||||
been added to each release, please refer to the [blog](https://blog.gitea.io).
 | 
			
		||||
 | 
			
		||||
## [1.14.0-RC1](https://github.com/go-gitea/gitea/releases/tag/v1.14.0) - 2021-03-19
 | 
			
		||||
## [1.14.0](https://github.com/go-gitea/gitea/releases/tag/v1.14.0) - 2021-04-11
 | 
			
		||||
 | 
			
		||||
* SECURITY
 | 
			
		||||
  * Respect approved email domain list for externally validated user registration (#15014)
 | 
			
		||||
  * Add reverse proxy configuration support for remote IP address detection (#14959)
 | 
			
		||||
  * Ensure validation occurs on clone addresses too (#14994)
 | 
			
		||||
  * Fix several render issues highlighted during fuzzing (#14986)
 | 
			
		||||
* BREAKING
 | 
			
		||||
  * Fix double 'push tag' action feed (#15078) (#15083)
 | 
			
		||||
  * Remove possible resource leak (#15067) (#15082)
 | 
			
		||||
  * Handle unauthorized user events gracefully (#15071) (#15074)
 | 
			
		||||
  * Restore Access.log following migration to Chi framework (Stops access logging of /api/internal routes) (#14475)
 | 
			
		||||
  * Migrate from Macaron to Chi framework (#14293)
 | 
			
		||||
  * Deprecate building for mips (#14174)
 | 
			
		||||
@@ -42,6 +44,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
 | 
			
		||||
  * Dump github/gitlab/gitea repository data to a local directory and restore to gitea (#12244)
 | 
			
		||||
  * Create Rootless Docker image (#10154)
 | 
			
		||||
* API
 | 
			
		||||
  * Speedup issue search (#15179) (#15192)
 | 
			
		||||
  * Get pull, return head branch sha, even if deleted (#14931)
 | 
			
		||||
  * Export LFS & TimeTracking function status (#14753)
 | 
			
		||||
  * Show Gitea version in swagger (#14654)
 | 
			
		||||
@@ -66,6 +69,20 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
 | 
			
		||||
  * Add more filters to issues search (#13514)
 | 
			
		||||
  * Add review request api (#11355)
 | 
			
		||||
* BUGFIXES
 | 
			
		||||
  * Fix delete nonexist oauth application 500 and prevent deadlock (#15384) (#15396)
 | 
			
		||||
  * Always set the merge base used to merge the commit (#15352) (#15385)
 | 
			
		||||
  * Upgrade to bluemonday 1.0.7 (#15379) (#15380)
 | 
			
		||||
  * Turn RepoRef and RepoAssignment back into func(*Context) (#15372) (#15377)
 | 
			
		||||
  * Move FCGI req.URL.Path fix-up to the FCGI listener (#15292) (#15361)
 | 
			
		||||
  * Show diff on rename with diff changes (#15338) (#15339)
 | 
			
		||||
  * Fix handling of logout event (#15323) (#15337)
 | 
			
		||||
  * Fix CanCreateRepo check (#15311) (#15321)
 | 
			
		||||
  * Fix xorm log stack level (#15285) (#15316)
 | 
			
		||||
  * Fix bug in Wrap (#15302) (#15309)
 | 
			
		||||
  * Drop the event source if we are unauthorized (#15275) (#15280)
 | 
			
		||||
  * Backport Fix graph pagination (#15225)  (#15249)
 | 
			
		||||
  * Prevent NPE in CommentMustAsDiff if no hunk header (#15199) (#15200)
 | 
			
		||||
  * should run RetrieveRepoMetas() for empty pr (#15187) (#15190)
 | 
			
		||||
  * Move setting to enable closing issue via commit in non default branch to repo settings (#14965)
 | 
			
		||||
  * Show correct issues for team dashboard (#14952)
 | 
			
		||||
  * Ensure that new pull request button works on forked forks owned by owner of the root and reduce ambiguity (#14932)
 | 
			
		||||
@@ -122,6 +139,9 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
 | 
			
		||||
  * Use GO variable in go-check target (#13146) (#13147)
 | 
			
		||||
* ENHANCEMENTS
 | 
			
		||||
  * UI style improvements
 | 
			
		||||
  * Dropzone styling improvements (#15291) (#15374)
 | 
			
		||||
  * Add size to Save function (#15264) (#15270)
 | 
			
		||||
  * Monaco improvements (#15333) (#15345)
 | 
			
		||||
  * Support .mailmap in code activity stats (#15009)
 | 
			
		||||
  * Sort release attachments by name (#15008)  
 | 
			
		||||
  * Add ui.explore settings to control view of explore pages (#14094)
 | 
			
		||||
@@ -267,6 +287,52 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
 | 
			
		||||
  * Reduce make verbosity (#13803)
 | 
			
		||||
  * Add git command error directory on log (#13194)
 | 
			
		||||
 | 
			
		||||
## [1.13.7](https://github.com/go-gitea/gitea/releases/tag/v1.13.7) - 2021-04-07
 | 
			
		||||
 | 
			
		||||
* SECURITY
 | 
			
		||||
  * Update to bluemonday-1.0.6 (#15294) (#15298)
 | 
			
		||||
  * Clusterfuzz found another way (#15160) (#15169)
 | 
			
		||||
* API
 | 
			
		||||
  * Fix wrong user returned in API (#15139) (#15150)
 | 
			
		||||
* BUGFIXES
 | 
			
		||||
  * Add 'fonts' into 'KnownPublicEntries' (#15188) (#15317)
 | 
			
		||||
  * Speed up `enry.IsVendor` (#15213) (#15246)
 | 
			
		||||
  * Response 404 for diff/patch of a commit that not exist (#15221) (#15238)
 | 
			
		||||
  * Prevent NPE in CommentMustAsDiff if no hunk header (#15199) (#15201)
 | 
			
		||||
* MISC
 | 
			
		||||
  * Add size to Save function (#15264) (#15271)
 | 
			
		||||
 | 
			
		||||
## [1.13.6](https://github.com/go-gitea/gitea/releases/tag/v1.13.6) - 2021-03-23
 | 
			
		||||
 | 
			
		||||
* SECURITY
 | 
			
		||||
  * Fix bug on avatar middleware (#15124) (#15125)
 | 
			
		||||
  * Fix another clusterfuzz identified issue (#15096) (#15114)
 | 
			
		||||
* API
 | 
			
		||||
  * Fix nil pointer exception in get pull reviews API (#15106)
 | 
			
		||||
* BUGFIXES
 | 
			
		||||
  * Fix markdown rendering in milestone content (#15056) (#15092)
 | 
			
		||||
 | 
			
		||||
## [1.13.5](https://github.com/go-gitea/gitea/releases/tag/v1.13.5) - 2021-03-21
 | 
			
		||||
 | 
			
		||||
* SECURITY
 | 
			
		||||
  * Update to goldmark 1.3.3 (#15059) (#15061)
 | 
			
		||||
  * Another clusterfuzz spotted issue (#15032) (#15034)
 | 
			
		||||
* API
 | 
			
		||||
  * Fix set milestone on PR creation (#14981) (#15001)
 | 
			
		||||
  * Prevent panic when editing forked repos by API (#14960) (#14963)
 | 
			
		||||
* BUGFIXES
 | 
			
		||||
  * Fix bug when upload on web (#15042) (#15055)
 | 
			
		||||
  * Delete Labels & IssueLabels on Repo Delete too (#15039) (#15051)
 | 
			
		||||
  * Fix postgres ID sequences broken by recreate-table (#15015) (#15029)
 | 
			
		||||
  * Fix several render issues (#14986) (#15013)
 | 
			
		||||
  * Make sure sibling images get a link too (#14979) (#14995)
 | 
			
		||||
  * Fix Anchor jumping with escaped query components (#14969) (#14977)
 | 
			
		||||
  * Fix release mail html template (#14976)
 | 
			
		||||
  * Fix excluding more than two labels on issues list (#14962) (#14973)
 | 
			
		||||
  * Don't mark each comment poster as OP (#14971) (#14972)
 | 
			
		||||
  * Add "captcha" to list of reserved usernames (#14930)
 | 
			
		||||
  * Re-enable import local paths after reversion from #13610 (#14925) (#14927)
 | 
			
		||||
 | 
			
		||||
## [1.13.4](https://github.com/go-gitea/gitea/releases/tag/v1.13.4) - 2021-03-07
 | 
			
		||||
 | 
			
		||||
* SECURITY
 | 
			
		||||
 
 | 
			
		||||
@@ -9,9 +9,11 @@ import (
 | 
			
		||||
	"net"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/http/fcgi"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/modules/graceful"
 | 
			
		||||
	"code.gitea.io/gitea/modules/log"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func runHTTP(network, listenAddr, name string, m http.Handler) error {
 | 
			
		||||
@@ -48,7 +50,12 @@ func runFCGI(network, listenAddr, name string, m http.Handler) error {
 | 
			
		||||
	fcgiServer := graceful.NewServer(network, listenAddr, name)
 | 
			
		||||
 | 
			
		||||
	err := fcgiServer.ListenAndServe(func(listener net.Listener) error {
 | 
			
		||||
		return fcgi.Serve(listener, m)
 | 
			
		||||
		return fcgi.Serve(listener, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
 | 
			
		||||
			if setting.AppSubURL != "" {
 | 
			
		||||
				req.URL.Path = strings.TrimPrefix(req.URL.Path, setting.AppSubURL)
 | 
			
		||||
			}
 | 
			
		||||
			m.ServeHTTP(resp, req)
 | 
			
		||||
		}))
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatal("Failed to start FCGI main server: %v", err)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								go.mod
									
									
									
									
									
								
							@@ -5,7 +5,7 @@ go 1.14
 | 
			
		||||
require (
 | 
			
		||||
	cloud.google.com/go v0.78.0 // indirect
 | 
			
		||||
	code.gitea.io/gitea-vet v0.2.1
 | 
			
		||||
	code.gitea.io/sdk/gitea v0.13.2
 | 
			
		||||
	code.gitea.io/sdk/gitea v0.14.0
 | 
			
		||||
	gitea.com/go-chi/binding v0.0.0-20210301195521-1fe1c9a555e7
 | 
			
		||||
	gitea.com/go-chi/cache v0.0.0-20210110083709-82c4c9ce2d5e
 | 
			
		||||
	gitea.com/go-chi/captcha v0.0.0-20210110083842-e7696c336a1e
 | 
			
		||||
@@ -86,7 +86,7 @@ require (
 | 
			
		||||
	github.com/mgechev/revive v1.0.3
 | 
			
		||||
	github.com/mholt/acmez v0.1.3 // indirect
 | 
			
		||||
	github.com/mholt/archiver/v3 v3.5.0
 | 
			
		||||
	github.com/microcosm-cc/bluemonday v1.0.4
 | 
			
		||||
	github.com/microcosm-cc/bluemonday v1.0.7
 | 
			
		||||
	github.com/miekg/dns v1.1.40 // indirect
 | 
			
		||||
	github.com/minio/md5-simd v1.1.2 // indirect
 | 
			
		||||
	github.com/minio/minio-go/v7 v7.0.10
 | 
			
		||||
@@ -128,7 +128,7 @@ require (
 | 
			
		||||
	github.com/xanzy/go-gitlab v0.44.0
 | 
			
		||||
	github.com/xanzy/ssh-agent v0.3.0 // indirect
 | 
			
		||||
	github.com/yohcop/openid-go v1.0.0
 | 
			
		||||
	github.com/yuin/goldmark v1.3.2
 | 
			
		||||
	github.com/yuin/goldmark v1.3.3
 | 
			
		||||
	github.com/yuin/goldmark-highlighting v0.0.0-20200307114337-60d527fdb691
 | 
			
		||||
	github.com/yuin/goldmark-meta v1.0.0
 | 
			
		||||
	go.jolheiser.com/hcaptcha v0.0.4
 | 
			
		||||
@@ -136,9 +136,9 @@ require (
 | 
			
		||||
	go.uber.org/multierr v1.6.0 // indirect
 | 
			
		||||
	go.uber.org/zap v1.16.0 // indirect
 | 
			
		||||
	golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83
 | 
			
		||||
	golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
 | 
			
		||||
	golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4
 | 
			
		||||
	golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93
 | 
			
		||||
	golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46
 | 
			
		||||
	golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44
 | 
			
		||||
	golang.org/x/text v0.3.5
 | 
			
		||||
	golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
 | 
			
		||||
	golang.org/x/tools v0.1.0
 | 
			
		||||
@@ -153,5 +153,3 @@ 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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										23
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								go.sum
									
									
									
									
									
								
							@@ -38,8 +38,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
 | 
			
		||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
 | 
			
		||||
code.gitea.io/gitea-vet v0.2.1 h1:b30by7+3SkmiftK0RjuXqFvZg2q4p68uoPGuxhzBN0s=
 | 
			
		||||
code.gitea.io/gitea-vet v0.2.1/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE=
 | 
			
		||||
code.gitea.io/sdk/gitea v0.13.2 h1:wAnT/J7Z62q3fJXbgnecoaOBh8CM1Qq0/DakWxiv4yA=
 | 
			
		||||
code.gitea.io/sdk/gitea v0.13.2/go.mod h1:lee2y8LeV3kQb2iK+hHlMqoadL4bp27QOkOV/hawLKg=
 | 
			
		||||
code.gitea.io/sdk/gitea v0.14.0 h1:m4J352I3p9+bmJUfS+g0odeQzBY/5OXP91Gv6D4fnJ0=
 | 
			
		||||
code.gitea.io/sdk/gitea v0.14.0/go.mod h1:89WiyOX1KEcvjP66sRHdu0RafojGo60bT9UqW17VbWs=
 | 
			
		||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
 | 
			
		||||
gitea.com/go-chi/binding v0.0.0-20210301195521-1fe1c9a555e7 h1:xCVJPY823C8RWpgMabTw2kOglDrg0iS3GcQU6wdwHkU=
 | 
			
		||||
gitea.com/go-chi/binding v0.0.0-20210301195521-1fe1c9a555e7/go.mod h1:AyfTrwtfYN54R/HmVvMYPnSTenH5bVoyh8x6tBluxEA=
 | 
			
		||||
@@ -196,8 +196,6 @@ github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+
 | 
			
		||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 | 
			
		||||
github.com/chi-middleware/proxy v1.1.1 h1:4HaXUp8o2+bhHr1OhVy+VjN0+L7/07JDcn6v7YrTjrQ=
 | 
			
		||||
github.com/chi-middleware/proxy v1.1.1/go.mod h1:jQwMEJct2tz9VmtCELxvnXoMfa+SOdikvbVJVHv/M+0=
 | 
			
		||||
github.com/chris-ramon/douceur v0.2.0 h1:IDMEdxlEUUBYBKE4z/mJnFyVXox+MjuEVDJNN27glkU=
 | 
			
		||||
github.com/chris-ramon/douceur v0.2.0/go.mod h1:wDW5xjJdeoMm1mRt4sD4c/LbF/mWdEpRXQKjTR8nIBE=
 | 
			
		||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
 | 
			
		||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
 | 
			
		||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
 | 
			
		||||
@@ -776,8 +774,6 @@ github.com/libdns/libdns v0.2.0 h1:ewg3ByWrdUrxrje8ChPVMBNcotg7H9LQYg+u5De2RzI=
 | 
			
		||||
github.com/libdns/libdns v0.2.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
 | 
			
		||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
 | 
			
		||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
 | 
			
		||||
github.com/lunny/bluemonday v1.0.5-0.20201227154428-ca34796141e8 h1:1omo92DLtxQu6VwVPSZAmduHaK5zssed6cvkHyl1XOg=
 | 
			
		||||
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/go.mod h1:3q8WtuPQsoRbatJuy3nvq/hRSvuBJrHHr+ybPPiNvHQ=
 | 
			
		||||
@@ -834,6 +830,8 @@ github.com/mholt/acmez v0.1.3 h1:J7MmNIk4Qf9b8mAGqAh4XkNeowv3f1zW816yf4zt7Qk=
 | 
			
		||||
github.com/mholt/acmez v0.1.3/go.mod h1:8qnn8QA/Ewx8E3ZSsmscqsIjhhpxuy9vqdgbX2ceceM=
 | 
			
		||||
github.com/mholt/archiver/v3 v3.5.0 h1:nE8gZIrw66cu4osS/U7UW7YDuGMHssxKutU8IfWxwWE=
 | 
			
		||||
github.com/mholt/archiver/v3 v3.5.0/go.mod h1:qqTTPUK/HZPFgFQ/TJ3BzvTpF/dPtFVJXdQbCmeMxwc=
 | 
			
		||||
github.com/microcosm-cc/bluemonday v1.0.7 h1:6yAQfk4XT+PI/dk1ZeBp1gr3Q2Hd1DR0O3aEyPUJVTE=
 | 
			
		||||
github.com/microcosm-cc/bluemonday v1.0.7/go.mod h1:HOT/6NaBlR0f9XlxD3zolN6Z3N8Lp4pvhp+jLS5ihnI=
 | 
			
		||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
 | 
			
		||||
github.com/miekg/dns v1.1.30/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
 | 
			
		||||
github.com/miekg/dns v1.1.40 h1:pyyPFfGMnciYUk/mXpKkVmeMQjfXqt3FAJ2hy7tPiLA=
 | 
			
		||||
@@ -1145,8 +1143,8 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
 | 
			
		||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 | 
			
		||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 | 
			
		||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 | 
			
		||||
github.com/yuin/goldmark v1.3.2 h1:YjHC5TgyMmHpicTgEqDN0Q96Xo8K6tLXPnmNOHXCgs0=
 | 
			
		||||
github.com/yuin/goldmark v1.3.2/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 | 
			
		||||
github.com/yuin/goldmark v1.3.3 h1:37BdQwPx8VOSic8eDSWee6QL9mRpZRm9VJp/QugNrW0=
 | 
			
		||||
github.com/yuin/goldmark v1.3.3/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 | 
			
		||||
github.com/yuin/goldmark-highlighting v0.0.0-20200307114337-60d527fdb691 h1:VWSxtAiQNh3zgHJpdpkpVYjTPqRE3P6UZCOPa1nRDio=
 | 
			
		||||
github.com/yuin/goldmark-highlighting v0.0.0-20200307114337-60d527fdb691/go.mod h1:YLF3kDffRfUH/bTxOxHhV6lxwIB3Vfj91rEwNMS9MXo=
 | 
			
		||||
github.com/yuin/goldmark-meta v1.0.0 h1:ScsatUIT2gFS6azqzLGUjgOnELsBOxMXerM3ogdJhAM=
 | 
			
		||||
@@ -1321,8 +1319,9 @@ golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwY
 | 
			
		||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
			
		||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
			
		||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
			
		||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
 | 
			
		||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
			
		||||
golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 | 
			
		||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
 | 
			
		||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 | 
			
		||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 | 
			
		||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 | 
			
		||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 | 
			
		||||
@@ -1418,8 +1417,8 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w
 | 
			
		||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46 h1:V066+OYJ66oTjnhm4Yrn7SXIwSCiDQJxpBxmvqb1N1c=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 | 
			
		||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
 | 
			
		||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
			
		||||
 
 | 
			
		||||
@@ -239,6 +239,26 @@ func doAPICreatePullRequest(ctx APITestContext, owner, repo, baseBranch, headBra
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func doAPIGetPullRequest(ctx APITestContext, owner, repo string, index int64) func(*testing.T) (api.PullRequest, error) {
 | 
			
		||||
	return func(t *testing.T) (api.PullRequest, error) {
 | 
			
		||||
		urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d?token=%s",
 | 
			
		||||
			owner, repo, index, ctx.Token)
 | 
			
		||||
		req := NewRequest(t, http.MethodGet, urlStr)
 | 
			
		||||
 | 
			
		||||
		expected := 200
 | 
			
		||||
		if ctx.ExpectedCode != 0 {
 | 
			
		||||
			expected = ctx.ExpectedCode
 | 
			
		||||
		}
 | 
			
		||||
		resp := ctx.Session.MakeRequest(t, req, expected)
 | 
			
		||||
 | 
			
		||||
		json := jsoniter.ConfigCompatibleWithStandardLibrary
 | 
			
		||||
		decoder := json.NewDecoder(resp.Body)
 | 
			
		||||
		pr := api.PullRequest{}
 | 
			
		||||
		err := decoder.Decode(&pr)
 | 
			
		||||
		return pr, err
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func doAPIMergePullRequest(ctx APITestContext, owner, repo string, index int64) func(*testing.T) {
 | 
			
		||||
	return func(t *testing.T) {
 | 
			
		||||
		urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d/merge?token=%s",
 | 
			
		||||
 
 | 
			
		||||
@@ -92,6 +92,10 @@ func testAPIDeleteOAuth2Application(t *testing.T) {
 | 
			
		||||
	session.MakeRequest(t, req, http.StatusNoContent)
 | 
			
		||||
 | 
			
		||||
	models.AssertNotExistsBean(t, &models.OAuth2Application{UID: oldApp.UID, Name: oldApp.Name})
 | 
			
		||||
 | 
			
		||||
	// Delete again will return not found
 | 
			
		||||
	req = NewRequest(t, "DELETE", urlStr)
 | 
			
		||||
	session.MakeRequest(t, req, http.StatusNotFound)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func testAPIGetOAuth2Application(t *testing.T) {
 | 
			
		||||
 
 | 
			
		||||
@@ -122,7 +122,7 @@ func TestGetAttachment(t *testing.T) {
 | 
			
		||||
		t.Run(tc.name, func(t *testing.T) {
 | 
			
		||||
			//Write empty file to be available for response
 | 
			
		||||
			if tc.createFile {
 | 
			
		||||
				_, err := storage.Attachments.Save(models.AttachmentRelativePath(tc.uuid), strings.NewReader("hello world"))
 | 
			
		||||
				_, err := storage.Attachments.Save(models.AttachmentRelativePath(tc.uuid), strings.NewReader("hello world"), -1)
 | 
			
		||||
				assert.NoError(t, err)
 | 
			
		||||
			}
 | 
			
		||||
			//Actual test
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@
 | 
			
		||||
package integrations
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"math/rand"
 | 
			
		||||
@@ -208,13 +209,13 @@ func rawTest(t *testing.T, ctx *APITestContext, little, big, littleLFS, bigLFS s
 | 
			
		||||
 | 
			
		||||
		// Request raw paths
 | 
			
		||||
		req := NewRequest(t, "GET", path.Join("/", username, reponame, "/raw/branch/master/", little))
 | 
			
		||||
		resp := session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
		assert.Equal(t, littleSize, resp.Body.Len())
 | 
			
		||||
		resp := session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
			
		||||
		assert.Equal(t, littleSize, resp.Length)
 | 
			
		||||
 | 
			
		||||
		setting.CheckLFSVersion()
 | 
			
		||||
		if setting.LFS.StartServer {
 | 
			
		||||
			req = NewRequest(t, "GET", path.Join("/", username, reponame, "/raw/branch/master/", littleLFS))
 | 
			
		||||
			resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
			resp := session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
			assert.NotEqual(t, littleSize, resp.Body.Len())
 | 
			
		||||
			assert.LessOrEqual(t, resp.Body.Len(), 1024)
 | 
			
		||||
			if resp.Body.Len() != littleSize && resp.Body.Len() <= 1024 {
 | 
			
		||||
@@ -224,12 +225,12 @@ func rawTest(t *testing.T, ctx *APITestContext, little, big, littleLFS, bigLFS s
 | 
			
		||||
 | 
			
		||||
		if !testing.Short() {
 | 
			
		||||
			req = NewRequest(t, "GET", path.Join("/", username, reponame, "/raw/branch/master/", big))
 | 
			
		||||
			resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
			assert.Equal(t, bigSize, resp.Body.Len())
 | 
			
		||||
			resp := session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
			
		||||
			assert.Equal(t, bigSize, resp.Length)
 | 
			
		||||
 | 
			
		||||
			if setting.LFS.StartServer {
 | 
			
		||||
				req = NewRequest(t, "GET", path.Join("/", username, reponame, "/raw/branch/master/", bigLFS))
 | 
			
		||||
				resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
				resp := session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
				assert.NotEqual(t, bigSize, resp.Body.Len())
 | 
			
		||||
				if resp.Body.Len() != bigSize && resp.Body.Len() <= 1024 {
 | 
			
		||||
					assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
 | 
			
		||||
@@ -450,27 +451,35 @@ func doMergeFork(ctx, baseCtx APITestContext, baseBranch, headBranch string) fun
 | 
			
		||||
		t.Run("EnsureCanSeePull", doEnsureCanSeePull(baseCtx, pr))
 | 
			
		||||
 | 
			
		||||
		// Then get the diff string
 | 
			
		||||
		var diffStr string
 | 
			
		||||
		var diffHash string
 | 
			
		||||
		var diffLength int
 | 
			
		||||
		t.Run("GetDiff", func(t *testing.T) {
 | 
			
		||||
			req := NewRequest(t, "GET", fmt.Sprintf("/%s/%s/pulls/%d.diff", url.PathEscape(baseCtx.Username), url.PathEscape(baseCtx.Reponame), pr.Index))
 | 
			
		||||
			resp := ctx.Session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
			diffStr = resp.Body.String()
 | 
			
		||||
			resp := ctx.Session.MakeRequestNilResponseHashSumRecorder(t, req, http.StatusOK)
 | 
			
		||||
			diffHash = string(resp.Hash.Sum(nil))
 | 
			
		||||
			diffLength = resp.Length
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		// Now: Merge the PR & make sure that doesn't break the PR page or change its diff
 | 
			
		||||
		t.Run("MergePR", doAPIMergePullRequest(baseCtx, baseCtx.Username, baseCtx.Reponame, pr.Index))
 | 
			
		||||
		t.Run("EnsureCanSeePull", doEnsureCanSeePull(baseCtx, pr))
 | 
			
		||||
		t.Run("EnsureDiffNoChange", doEnsureDiffNoChange(baseCtx, pr, diffStr))
 | 
			
		||||
		t.Run("CheckPR", func(t *testing.T) {
 | 
			
		||||
			oldMergeBase := pr.MergeBase
 | 
			
		||||
			pr2, err := doAPIGetPullRequest(baseCtx, baseCtx.Username, baseCtx.Reponame, pr.Index)(t)
 | 
			
		||||
			assert.NoError(t, err)
 | 
			
		||||
			assert.Equal(t, oldMergeBase, pr2.MergeBase)
 | 
			
		||||
		})
 | 
			
		||||
		t.Run("EnsurDiffNoChange", doEnsureDiffNoChange(baseCtx, pr, diffHash, diffLength))
 | 
			
		||||
 | 
			
		||||
		// Then: Delete the head branch & make sure that doesn't break the PR page or change its diff
 | 
			
		||||
		t.Run("DeleteHeadBranch", doBranchDelete(baseCtx, baseCtx.Username, baseCtx.Reponame, headBranch))
 | 
			
		||||
		t.Run("EnsureCanSeePull", doEnsureCanSeePull(baseCtx, pr))
 | 
			
		||||
		t.Run("EnsureDiffNoChange", doEnsureDiffNoChange(baseCtx, pr, diffStr))
 | 
			
		||||
		t.Run("EnsureDiffNoChange", doEnsureDiffNoChange(baseCtx, pr, diffHash, diffLength))
 | 
			
		||||
 | 
			
		||||
		// Delete the head repository & make sure that doesn't break the PR page or change its diff
 | 
			
		||||
		t.Run("DeleteHeadRepository", doAPIDeleteRepository(ctx))
 | 
			
		||||
		t.Run("EnsureCanSeePull", doEnsureCanSeePull(baseCtx, pr))
 | 
			
		||||
		t.Run("EnsureDiffNoChange", doEnsureDiffNoChange(baseCtx, pr, diffStr))
 | 
			
		||||
		t.Run("EnsureDiffNoChange", doEnsureDiffNoChange(baseCtx, pr, diffHash, diffLength))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -514,20 +523,15 @@ func doEnsureCanSeePull(ctx APITestContext, pr api.PullRequest) func(t *testing.
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func doEnsureDiffNoChange(ctx APITestContext, pr api.PullRequest, diffStr string) func(t *testing.T) {
 | 
			
		||||
func doEnsureDiffNoChange(ctx APITestContext, pr api.PullRequest, diffHash string, diffLength int) func(t *testing.T) {
 | 
			
		||||
	return func(t *testing.T) {
 | 
			
		||||
		req := NewRequest(t, "GET", fmt.Sprintf("/%s/%s/pulls/%d.diff", url.PathEscape(ctx.Username), url.PathEscape(ctx.Reponame), pr.Index))
 | 
			
		||||
		resp := ctx.Session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
		expectedMaxLen := len(diffStr)
 | 
			
		||||
		if expectedMaxLen > 800 {
 | 
			
		||||
			expectedMaxLen = 800
 | 
			
		||||
		}
 | 
			
		||||
		actual := resp.Body.String()
 | 
			
		||||
		actualMaxLen := len(actual)
 | 
			
		||||
		if actualMaxLen > 800 {
 | 
			
		||||
			actualMaxLen = 800
 | 
			
		||||
		}
 | 
			
		||||
		assert.Equal(t, diffStr, actual, "Unexpected change in the diff string: expected: %s but was actually: %s", diffStr[:expectedMaxLen], actual[:actualMaxLen])
 | 
			
		||||
		resp := ctx.Session.MakeRequestNilResponseHashSumRecorder(t, req, http.StatusOK)
 | 
			
		||||
		actual := string(resp.Hash.Sum(nil))
 | 
			
		||||
		actualLength := resp.Length
 | 
			
		||||
 | 
			
		||||
		equal := diffHash == actual
 | 
			
		||||
		assert.True(t, equal, "Unexpected change in the diff string: expected hash: %s size: %d but was actually: %s size: %d", hex.EncodeToString([]byte(diffHash)), diffLength, hex.EncodeToString([]byte(actual)), actualLength)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,8 @@ import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"hash"
 | 
			
		||||
	"hash/fnv"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/http/cookiejar"
 | 
			
		||||
@@ -58,6 +60,26 @@ func NewNilResponseRecorder() *NilResponseRecorder {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type NilResponseHashSumRecorder struct {
 | 
			
		||||
	httptest.ResponseRecorder
 | 
			
		||||
	Hash   hash.Hash
 | 
			
		||||
	Length int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (n *NilResponseHashSumRecorder) Write(b []byte) (int, error) {
 | 
			
		||||
	_, _ = n.Hash.Write(b)
 | 
			
		||||
	n.Length += len(b)
 | 
			
		||||
	return len(b), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewRecorder returns an initialized ResponseRecorder.
 | 
			
		||||
func NewNilResponseHashSumRecorder() *NilResponseHashSumRecorder {
 | 
			
		||||
	return &NilResponseHashSumRecorder{
 | 
			
		||||
		Hash:             fnv.New32(),
 | 
			
		||||
		ResponseRecorder: *httptest.NewRecorder(),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMain(m *testing.M) {
 | 
			
		||||
	defer log.Close()
 | 
			
		||||
 | 
			
		||||
@@ -284,6 +306,23 @@ func (s *TestSession) MakeRequestNilResponseRecorder(t testing.TB, req *http.Req
 | 
			
		||||
	return resp
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *TestSession) MakeRequestNilResponseHashSumRecorder(t testing.TB, req *http.Request, expectedStatus int) *NilResponseHashSumRecorder {
 | 
			
		||||
	t.Helper()
 | 
			
		||||
	baseURL, err := url.Parse(setting.AppURL)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	for _, c := range s.jar.Cookies(baseURL) {
 | 
			
		||||
		req.AddCookie(c)
 | 
			
		||||
	}
 | 
			
		||||
	resp := MakeRequestNilResponseHashSumRecorder(t, req, expectedStatus)
 | 
			
		||||
 | 
			
		||||
	ch := http.Header{}
 | 
			
		||||
	ch.Add("Cookie", strings.Join(resp.Header()["Set-Cookie"], ";"))
 | 
			
		||||
	cr := http.Request{Header: ch}
 | 
			
		||||
	s.jar.SetCookies(baseURL, cr.Cookies())
 | 
			
		||||
 | 
			
		||||
	return resp
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const userPassword = "password"
 | 
			
		||||
 | 
			
		||||
var loginSessionCache = make(map[string]*TestSession, 10)
 | 
			
		||||
@@ -429,6 +468,19 @@ func MakeRequestNilResponseRecorder(t testing.TB, req *http.Request, expectedSta
 | 
			
		||||
	return recorder
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func MakeRequestNilResponseHashSumRecorder(t testing.TB, req *http.Request, expectedStatus int) *NilResponseHashSumRecorder {
 | 
			
		||||
	t.Helper()
 | 
			
		||||
	recorder := NewNilResponseHashSumRecorder()
 | 
			
		||||
	c.ServeHTTP(recorder, req)
 | 
			
		||||
	if expectedStatus != NoExpectedStatus {
 | 
			
		||||
		if !assert.EqualValues(t, expectedStatus, recorder.Code,
 | 
			
		||||
			"Request: %s %s", req.Method, req.URL.String()) {
 | 
			
		||||
			logUnexpectedResponse(t, &recorder.ResponseRecorder)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return recorder
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// logUnexpectedResponse logs the contents of an unexpected response.
 | 
			
		||||
func logUnexpectedResponse(t testing.TB, recorder *httptest.ResponseRecorder) {
 | 
			
		||||
	t.Helper()
 | 
			
		||||
 
 | 
			
		||||
@@ -382,7 +382,7 @@ func activityQueryCondition(opts GetFeedsOptions) (builder.Cond, error) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.Date != "" {
 | 
			
		||||
		dateLow, err := time.Parse("2006-01-02", opts.Date)
 | 
			
		||||
		dateLow, err := time.ParseInLocation("2006-01-02", opts.Date, setting.DefaultUILocation)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Warn("Unable to parse %s, filter not applied: %v", opts.Date, err)
 | 
			
		||||
		} else {
 | 
			
		||||
 
 | 
			
		||||
@@ -85,7 +85,7 @@ func (a *Attachment) LinkedRepository() (*Repository, UnitType, error) {
 | 
			
		||||
func NewAttachment(attach *Attachment, buf []byte, file io.Reader) (_ *Attachment, err error) {
 | 
			
		||||
	attach.UUID = gouuid.New().String()
 | 
			
		||||
 | 
			
		||||
	size, err := storage.Attachments.Save(attach.RelativePath(), io.MultiReader(bytes.NewReader(buf), file))
 | 
			
		||||
	size, err := storage.Attachments.Save(attach.RelativePath(), io.MultiReader(bytes.NewReader(buf), file), -1)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("Create: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -338,7 +338,7 @@ func FixCommentTypeLabelWithEmptyLabel() (int64, error) {
 | 
			
		||||
 | 
			
		||||
// CountCommentTypeLabelWithOutsideLabels count label comments with outside label
 | 
			
		||||
func CountCommentTypeLabelWithOutsideLabels() (int64, error) {
 | 
			
		||||
	return x.Where("comment.type = ? AND (issue.repo_id != label.repo_id OR (label.repo_id = 0 AND repository.owner_id != label.org_id))", CommentTypeLabel).
 | 
			
		||||
	return x.Where("comment.type = ? AND ((label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id))", CommentTypeLabel).
 | 
			
		||||
		Table("comment").
 | 
			
		||||
		Join("inner", "label", "label.id = comment.label_id").
 | 
			
		||||
		Join("inner", "issue", "issue.id = comment.issue_id ").
 | 
			
		||||
@@ -354,8 +354,9 @@ func FixCommentTypeLabelWithOutsideLabels() (int64, error) {
 | 
			
		||||
				FROM comment AS com
 | 
			
		||||
					INNER JOIN label ON com.label_id = label.id
 | 
			
		||||
					INNER JOIN issue on issue.id = com.issue_id
 | 
			
		||||
					INNER JOIN repository ON issue.repo_id = repository.id
 | 
			
		||||
				WHERE
 | 
			
		||||
					com.type = ? AND (issue.repo_id != label.repo_id OR (label.repo_id = 0 AND label.org_id != repo.owner_id))
 | 
			
		||||
					com.type = ? AND ((label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id))
 | 
			
		||||
	) AS il_too)`, CommentTypeLabel)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
@@ -366,9 +367,9 @@ func FixCommentTypeLabelWithOutsideLabels() (int64, error) {
 | 
			
		||||
 | 
			
		||||
// CountIssueLabelWithOutsideLabels count label comments with outside label
 | 
			
		||||
func CountIssueLabelWithOutsideLabels() (int64, error) {
 | 
			
		||||
	return x.Where(builder.Expr("issue.repo_id != label.repo_id OR (label.repo_id = 0 AND repository.owner_id != label.org_id)")).
 | 
			
		||||
	return x.Where(builder.Expr("(label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id)")).
 | 
			
		||||
		Table("issue_label").
 | 
			
		||||
		Join("inner", "label", "issue_label.id = label.id ").
 | 
			
		||||
		Join("inner", "label", "issue_label.label_id = label.id ").
 | 
			
		||||
		Join("inner", "issue", "issue.id = issue_label.issue_id ").
 | 
			
		||||
		Join("inner", "repository", "issue.repo_id = repository.id").
 | 
			
		||||
		Count(new(IssueLabel))
 | 
			
		||||
@@ -380,11 +381,11 @@ func FixIssueLabelWithOutsideLabels() (int64, error) {
 | 
			
		||||
		SELECT il_too.id FROM (
 | 
			
		||||
			SELECT il_too_too.id
 | 
			
		||||
				FROM issue_label AS il_too_too
 | 
			
		||||
					INNER JOIN label ON il_too_too.id = label.id
 | 
			
		||||
					INNER JOIN label ON il_too_too.label_id = label.id
 | 
			
		||||
					INNER JOIN issue on issue.id = il_too_too.issue_id
 | 
			
		||||
					INNER JOIN repository on repository.id = issue.repo_id
 | 
			
		||||
				WHERE
 | 
			
		||||
					issue.repo_id != label.repo_id OR (label.repo_id = 0 AND label.org_id != repository.owner_id)
 | 
			
		||||
					(label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id)
 | 
			
		||||
	) AS il_too )`)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,8 @@ func NewXORMLogger(showSQL bool) xormlog.Logger {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const stackLevel = 8
 | 
			
		||||
 | 
			
		||||
// Log a message with defined skip and at logging level
 | 
			
		||||
func (l *XORMLogBridge) Log(skip int, level log.Level, format string, v ...interface{}) error {
 | 
			
		||||
	return l.logger.Log(skip+1, level, format, v...)
 | 
			
		||||
@@ -33,42 +35,42 @@ func (l *XORMLogBridge) Log(skip int, level log.Level, format string, v ...inter
 | 
			
		||||
 | 
			
		||||
// Debug show debug log
 | 
			
		||||
func (l *XORMLogBridge) Debug(v ...interface{}) {
 | 
			
		||||
	_ = l.Log(2, log.DEBUG, fmt.Sprint(v...))
 | 
			
		||||
	_ = l.Log(stackLevel, log.DEBUG, fmt.Sprint(v...))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Debugf show debug log
 | 
			
		||||
func (l *XORMLogBridge) Debugf(format string, v ...interface{}) {
 | 
			
		||||
	_ = l.Log(2, log.DEBUG, format, v...)
 | 
			
		||||
	_ = l.Log(stackLevel, log.DEBUG, format, v...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Error show error log
 | 
			
		||||
func (l *XORMLogBridge) Error(v ...interface{}) {
 | 
			
		||||
	_ = l.Log(2, log.ERROR, fmt.Sprint(v...))
 | 
			
		||||
	_ = l.Log(stackLevel, log.ERROR, fmt.Sprint(v...))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Errorf show error log
 | 
			
		||||
func (l *XORMLogBridge) Errorf(format string, v ...interface{}) {
 | 
			
		||||
	_ = l.Log(2, log.ERROR, format, v...)
 | 
			
		||||
	_ = l.Log(stackLevel, log.ERROR, format, v...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Info show information level log
 | 
			
		||||
func (l *XORMLogBridge) Info(v ...interface{}) {
 | 
			
		||||
	_ = l.Log(2, log.INFO, fmt.Sprint(v...))
 | 
			
		||||
	_ = l.Log(stackLevel, log.INFO, fmt.Sprint(v...))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Infof show information level log
 | 
			
		||||
func (l *XORMLogBridge) Infof(format string, v ...interface{}) {
 | 
			
		||||
	_ = l.Log(2, log.INFO, format, v...)
 | 
			
		||||
	_ = l.Log(stackLevel, log.INFO, format, v...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Warn show warning log
 | 
			
		||||
func (l *XORMLogBridge) Warn(v ...interface{}) {
 | 
			
		||||
	_ = l.Log(2, log.WARN, fmt.Sprint(v...))
 | 
			
		||||
	_ = l.Log(stackLevel, log.WARN, fmt.Sprint(v...))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Warnf show warnning log
 | 
			
		||||
func (l *XORMLogBridge) Warnf(format string, v ...interface{}) {
 | 
			
		||||
	_ = l.Log(2, log.WARN, format, v...)
 | 
			
		||||
	_ = l.Log(stackLevel, log.WARN, format, v...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Level get logger level
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,7 @@ func InsertMilestones(ms ...*Milestone) (err error) {
 | 
			
		||||
// InsertIssues insert issues to database
 | 
			
		||||
func InsertIssues(issues ...*Issue) error {
 | 
			
		||||
	sess := x.NewSession()
 | 
			
		||||
	defer sess.Close()
 | 
			
		||||
	if err := sess.Begin(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@@ -194,6 +195,7 @@ func InsertPullRequests(prs ...*PullRequest) error {
 | 
			
		||||
// InsertReleases migrates release
 | 
			
		||||
func InsertReleases(rels ...*Release) error {
 | 
			
		||||
	sess := x.NewSession()
 | 
			
		||||
	defer sess.Close()
 | 
			
		||||
	if err := sess.Begin(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -48,11 +48,11 @@ func removeInvalidLabels(x *xorm.Engine) error {
 | 
			
		||||
		SELECT il_too.id FROM (
 | 
			
		||||
			SELECT il_too_too.id
 | 
			
		||||
				FROM issue_label AS il_too_too
 | 
			
		||||
					INNER JOIN label ON il_too_too.id = label.id
 | 
			
		||||
					INNER JOIN label ON il_too_too.label_id = label.id
 | 
			
		||||
					INNER JOIN issue on issue.id = il_too_too.issue_id
 | 
			
		||||
					INNER JOIN repository on repository.id = issue.repo_id
 | 
			
		||||
				WHERE
 | 
			
		||||
					issue.repo_id != label.repo_id OR (label.repo_id = 0 AND label.org_id != repository.owner_id)
 | 
			
		||||
					(label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id)
 | 
			
		||||
	) AS il_too )`); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@@ -65,7 +65,7 @@ func removeInvalidLabels(x *xorm.Engine) error {
 | 
			
		||||
					INNER JOIN issue on issue.id = com.issue_id
 | 
			
		||||
					INNER JOIN repository on repository.id = issue.repo_id
 | 
			
		||||
				WHERE
 | 
			
		||||
					com.type = ? AND (issue.repo_id != label.repo_id OR (label.repo_id = 0 AND label.org_id != repository.owner_id))
 | 
			
		||||
					com.type = ? AND ((label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id))
 | 
			
		||||
	) AS il_too)`, 7); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -235,7 +235,7 @@ func deleteOAuth2Application(sess *xorm.Session, id, userid int64) error {
 | 
			
		||||
	if deleted, err := sess.Delete(&OAuth2Application{ID: id, UID: userid}); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	} else if deleted == 0 {
 | 
			
		||||
		return fmt.Errorf("cannot find oauth2 application")
 | 
			
		||||
		return ErrOAuthApplicationNotFound{ID: id}
 | 
			
		||||
	}
 | 
			
		||||
	codes := make([]*OAuth2AuthorizationCode, 0)
 | 
			
		||||
	// delete correlating auth codes
 | 
			
		||||
@@ -261,6 +261,7 @@ func deleteOAuth2Application(sess *xorm.Session, id, userid int64) error {
 | 
			
		||||
// DeleteOAuth2Application deletes the application with the given id and the grants and auth codes related to it. It checks if the userid was the creator of the app.
 | 
			
		||||
func DeleteOAuth2Application(id, userid int64) error {
 | 
			
		||||
	sess := x.NewSession()
 | 
			
		||||
	defer sess.Close()
 | 
			
		||||
	if err := sess.Begin(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -406,7 +406,8 @@ func (pr *PullRequest) SetMerged() (bool, error) {
 | 
			
		||||
		return false, fmt.Errorf("Issue.changeStatus: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, err := sess.Where("id = ?", pr.ID).Cols("has_merged, status, merged_commit_id, merger_id, merged_unix").Update(pr); err != nil {
 | 
			
		||||
	// We need to save all of the data used to compute this merge as it may have already been changed by TestPatch. FIXME: need to set some state to prevent TestPatch from running whilst we are merging.
 | 
			
		||||
	if _, err := sess.Where("id = ?", pr.ID).Cols("has_merged, status, merge_base, merged_commit_id, merger_id, merged_unix").Update(pr); err != nil {
 | 
			
		||||
		return false, fmt.Errorf("Failed to update pr[%d]: %v", pr.ID, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,7 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/modules/util"
 | 
			
		||||
 | 
			
		||||
	"xorm.io/builder"
 | 
			
		||||
	"xorm.io/xorm"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// RepositoryListDefaultPageSize is the default number of repositories
 | 
			
		||||
@@ -363,6 +364,35 @@ func SearchRepository(opts *SearchRepoOptions) (RepositoryList, int64, error) {
 | 
			
		||||
 | 
			
		||||
// SearchRepositoryByCondition search repositories by condition
 | 
			
		||||
func SearchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond, loadAttributes bool) (RepositoryList, int64, error) {
 | 
			
		||||
	sess, count, err := searchRepositoryByCondition(opts, cond)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, 0, err
 | 
			
		||||
	}
 | 
			
		||||
	defer sess.Close()
 | 
			
		||||
 | 
			
		||||
	defaultSize := 50
 | 
			
		||||
	if opts.PageSize > 0 {
 | 
			
		||||
		defaultSize = opts.PageSize
 | 
			
		||||
	}
 | 
			
		||||
	repos := make(RepositoryList, 0, defaultSize)
 | 
			
		||||
	if err := sess.Find(&repos); err != nil {
 | 
			
		||||
		return nil, 0, fmt.Errorf("Repo: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.PageSize <= 0 {
 | 
			
		||||
		count = int64(len(repos))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if loadAttributes {
 | 
			
		||||
		if err := repos.loadAttributes(sess); err != nil {
 | 
			
		||||
			return nil, 0, fmt.Errorf("LoadAttributes: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return repos, count, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func searchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond) (*xorm.Session, int64, error) {
 | 
			
		||||
	if opts.Page <= 0 {
 | 
			
		||||
		opts.Page = 1
 | 
			
		||||
	}
 | 
			
		||||
@@ -376,31 +406,24 @@ func SearchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond, loa
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sess := x.NewSession()
 | 
			
		||||
	defer sess.Close()
 | 
			
		||||
 | 
			
		||||
	count, err := sess.
 | 
			
		||||
	var count int64
 | 
			
		||||
	if opts.PageSize > 0 {
 | 
			
		||||
		var err error
 | 
			
		||||
		count, err = sess.
 | 
			
		||||
			Where(cond).
 | 
			
		||||
			Count(new(Repository))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			_ = sess.Close()
 | 
			
		||||
			return nil, 0, fmt.Errorf("Count: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	repos := make(RepositoryList, 0, opts.PageSize)
 | 
			
		||||
	sess.Where(cond).OrderBy(opts.OrderBy.String())
 | 
			
		||||
	if opts.PageSize > 0 {
 | 
			
		||||
		sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
 | 
			
		||||
	}
 | 
			
		||||
	if err = sess.Find(&repos); err != nil {
 | 
			
		||||
		return nil, 0, fmt.Errorf("Repo: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if loadAttributes {
 | 
			
		||||
		if err = repos.loadAttributes(sess); err != nil {
 | 
			
		||||
			return nil, 0, fmt.Errorf("LoadAttributes: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return repos, count, nil
 | 
			
		||||
	return sess, count, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// accessibleRepositoryCondition takes a user a returns a condition for checking if a repository is accessible
 | 
			
		||||
@@ -456,6 +479,33 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err
 | 
			
		||||
	return SearchRepository(opts)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SearchRepositoryIDs takes keyword and part of repository name to search,
 | 
			
		||||
// it returns results in given range and number of total results.
 | 
			
		||||
func SearchRepositoryIDs(opts *SearchRepoOptions) ([]int64, int64, error) {
 | 
			
		||||
	opts.IncludeDescription = false
 | 
			
		||||
 | 
			
		||||
	cond := SearchRepositoryCondition(opts)
 | 
			
		||||
 | 
			
		||||
	sess, count, err := searchRepositoryByCondition(opts, cond)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, 0, err
 | 
			
		||||
	}
 | 
			
		||||
	defer sess.Close()
 | 
			
		||||
 | 
			
		||||
	defaultSize := 50
 | 
			
		||||
	if opts.PageSize > 0 {
 | 
			
		||||
		defaultSize = opts.PageSize
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ids := make([]int64, 0, defaultSize)
 | 
			
		||||
	err = sess.Select("id").Table("repository").Find(&ids)
 | 
			
		||||
	if opts.PageSize <= 0 {
 | 
			
		||||
		count = int64(len(ids))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ids, count, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AccessibleRepoIDsQuery queries accessible repository ids. Usable as a subquery wherever repo ids need to be filtered.
 | 
			
		||||
func AccessibleRepoIDsQuery(user *User) *builder.Builder {
 | 
			
		||||
	// NB: Please note this code needs to still work if user is nil
 | 
			
		||||
 
 | 
			
		||||
@@ -330,10 +330,10 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) (err e
 | 
			
		||||
			SELECT il_too.id FROM (
 | 
			
		||||
				SELECT il_too_too.id
 | 
			
		||||
					FROM issue_label AS il_too_too
 | 
			
		||||
						INNER JOIN label ON il_too_too.id = label.id
 | 
			
		||||
						INNER JOIN label ON il_too_too.label_id = label.id
 | 
			
		||||
						INNER JOIN issue on issue.id = il_too_too.issue_id
 | 
			
		||||
					WHERE
 | 
			
		||||
						issue.repo_id = ? AND (issue.repo_id != label.repo_id OR (label.repo_id = 0 AND label.org_id != ?))
 | 
			
		||||
						issue.repo_id = ? AND ((label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != ?))
 | 
			
		||||
		) AS il_too )`, repo.ID, newOwner.ID); err != nil {
 | 
			
		||||
			return fmt.Errorf("Unable to remove old org labels: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
@@ -343,9 +343,9 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) (err e
 | 
			
		||||
				SELECT com.id
 | 
			
		||||
					FROM comment AS com
 | 
			
		||||
						INNER JOIN label ON com.label_id = label.id
 | 
			
		||||
						INNER JOIN issue on issue.id = com.issue_id
 | 
			
		||||
						INNER JOIN issue ON issue.id = com.issue_id
 | 
			
		||||
					WHERE
 | 
			
		||||
						com.type = ? AND issue.repo_id = ? AND (issue.repo_id != label.repo_id OR (label.repo_id = 0 AND label.org_id != ?))
 | 
			
		||||
						com.type = ? AND issue.repo_id = ? AND ((label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != ?))
 | 
			
		||||
		) AS il_too)`, CommentTypeLabel, repo.ID, newOwner.ID); err != nil {
 | 
			
		||||
			return fmt.Errorf("Unable to remove old org label comments: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -239,10 +239,10 @@ func (u *User) GetEmail() string {
 | 
			
		||||
	return u.Email
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetAllUsers returns a slice of all users found in DB.
 | 
			
		||||
// GetAllUsers returns a slice of all individual users found in DB.
 | 
			
		||||
func GetAllUsers() ([]*User, error) {
 | 
			
		||||
	users := make([]*User, 0)
 | 
			
		||||
	return users, x.OrderBy("id").Find(&users)
 | 
			
		||||
	return users, x.OrderBy("id").Where("type = ?", UserTypeIndividual).Find(&users)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsLocal returns true if user login type is LoginPlain.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										70
									
								
								modules/analyze/vendor.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								modules/analyze/vendor.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
// 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 analyze
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/go-enry/go-enry/v2/data"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var isVendorRegExp *regexp.Regexp
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	matchers := data.VendorMatchers
 | 
			
		||||
 | 
			
		||||
	caretStrings := make([]string, 0, 10)
 | 
			
		||||
	caretShareStrings := make([]string, 0, 10)
 | 
			
		||||
 | 
			
		||||
	matcherStrings := make([]string, 0, len(matchers))
 | 
			
		||||
	for _, matcher := range matchers {
 | 
			
		||||
		str := matcher.String()
 | 
			
		||||
		if str[0] == '^' {
 | 
			
		||||
			caretStrings = append(caretStrings, str[1:])
 | 
			
		||||
		} else if str[0:5] == "(^|/)" {
 | 
			
		||||
			caretShareStrings = append(caretShareStrings, str[5:])
 | 
			
		||||
		} else {
 | 
			
		||||
			matcherStrings = append(matcherStrings, str)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sort.Strings(caretShareStrings)
 | 
			
		||||
	sort.Strings(caretStrings)
 | 
			
		||||
	sort.Strings(matcherStrings)
 | 
			
		||||
 | 
			
		||||
	sb := &strings.Builder{}
 | 
			
		||||
	sb.WriteString("(?:^(?:")
 | 
			
		||||
	sb.WriteString(caretStrings[0])
 | 
			
		||||
	for _, matcher := range caretStrings[1:] {
 | 
			
		||||
		sb.WriteString(")|(?:")
 | 
			
		||||
		sb.WriteString(matcher)
 | 
			
		||||
	}
 | 
			
		||||
	sb.WriteString("))")
 | 
			
		||||
	sb.WriteString("|")
 | 
			
		||||
	sb.WriteString("(?:(?:^|/)(?:")
 | 
			
		||||
	sb.WriteString(caretShareStrings[0])
 | 
			
		||||
	for _, matcher := range caretShareStrings[1:] {
 | 
			
		||||
		sb.WriteString(")|(?:")
 | 
			
		||||
		sb.WriteString(matcher)
 | 
			
		||||
	}
 | 
			
		||||
	sb.WriteString("))")
 | 
			
		||||
	sb.WriteString("|")
 | 
			
		||||
	sb.WriteString("(?:")
 | 
			
		||||
	sb.WriteString(matcherStrings[0])
 | 
			
		||||
	for _, matcher := range matcherStrings[1:] {
 | 
			
		||||
		sb.WriteString(")|(?:")
 | 
			
		||||
		sb.WriteString(matcher)
 | 
			
		||||
	}
 | 
			
		||||
	sb.WriteString(")")
 | 
			
		||||
	combined := sb.String()
 | 
			
		||||
	isVendorRegExp = regexp.MustCompile(combined)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsVendor returns whether or not path is a vendor path.
 | 
			
		||||
func IsVendor(path string) bool {
 | 
			
		||||
	return isVendorRegExp.MatchString(path)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								modules/analyze/vendor_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								modules/analyze/vendor_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
// 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 analyze
 | 
			
		||||
 | 
			
		||||
import "testing"
 | 
			
		||||
 | 
			
		||||
func TestIsVendor(t *testing.T) {
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		path string
 | 
			
		||||
		want bool
 | 
			
		||||
	}{
 | 
			
		||||
		{"cache/", true},
 | 
			
		||||
		{"random/cache/", true},
 | 
			
		||||
		{"cache", false},
 | 
			
		||||
		{"dependencies/", true},
 | 
			
		||||
		{"Dependencies/", true},
 | 
			
		||||
		{"dependency/", false},
 | 
			
		||||
		{"dist/", true},
 | 
			
		||||
		{"dist", false},
 | 
			
		||||
		{"random/dist/", true},
 | 
			
		||||
		{"random/dist", false},
 | 
			
		||||
		{"deps/", true},
 | 
			
		||||
		{"configure", true},
 | 
			
		||||
		{"a/configure", true},
 | 
			
		||||
		{"config.guess", true},
 | 
			
		||||
		{"config.guess/", false},
 | 
			
		||||
		{".vscode/", true},
 | 
			
		||||
		{"doc/_build/", true},
 | 
			
		||||
		{"a/docs/_build/", true},
 | 
			
		||||
		{"a/dasdocs/_build-vsdoc.js", true},
 | 
			
		||||
		{"a/dasdocs/_build-vsdoc.j", false},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.path, func(t *testing.T) {
 | 
			
		||||
			if got := IsVendor(tt.path); got != tt.want {
 | 
			
		||||
				t.Errorf("IsVendor() = %v, want %v", got, tt.want)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -8,7 +8,6 @@ package context
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"path"
 | 
			
		||||
	"strings"
 | 
			
		||||
@@ -394,13 +393,10 @@ func RepoIDAssignment() func(ctx *Context) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RepoAssignment returns a middleware to handle repository assignment
 | 
			
		||||
func RepoAssignment() func(http.Handler) http.Handler {
 | 
			
		||||
	return func(next http.Handler) http.Handler {
 | 
			
		||||
		return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
func RepoAssignment(ctx *Context) {
 | 
			
		||||
	var (
 | 
			
		||||
		owner *models.User
 | 
			
		||||
		err   error
 | 
			
		||||
				ctx   = GetContext(req)
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	userName := ctx.Params(":username")
 | 
			
		||||
@@ -543,7 +539,6 @@ func RepoAssignment() func(http.Handler) http.Handler {
 | 
			
		||||
	// Stop at this point when the repo is empty.
 | 
			
		||||
	if ctx.Repo.Repository.IsEmpty {
 | 
			
		||||
		ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
 | 
			
		||||
				next.ServeHTTP(w, req)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -624,9 +619,6 @@ func RepoAssignment() func(http.Handler) http.Handler {
 | 
			
		||||
		ctx.Data["GoDocDirectory"] = prefix + "{/dir}"
 | 
			
		||||
		ctx.Data["GoDocFile"] = prefix + "{/dir}/{file}#L{line}"
 | 
			
		||||
	}
 | 
			
		||||
			next.ServeHTTP(w, req)
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RepoRefType type of repo reference
 | 
			
		||||
@@ -651,7 +643,7 @@ const (
 | 
			
		||||
 | 
			
		||||
// RepoRef handles repository reference names when the ref name is not
 | 
			
		||||
// explicitly given
 | 
			
		||||
func RepoRef() func(http.Handler) http.Handler {
 | 
			
		||||
func RepoRef() func(*Context) {
 | 
			
		||||
	// since no ref name is explicitly specified, ok to just use branch
 | 
			
		||||
	return RepoRefByType(RepoRefBranch)
 | 
			
		||||
}
 | 
			
		||||
@@ -730,10 +722,8 @@ func getRefName(ctx *Context, pathType RepoRefType) string {
 | 
			
		||||
 | 
			
		||||
// RepoRefByType handles repository reference name for a specific type
 | 
			
		||||
// of repository reference
 | 
			
		||||
func RepoRefByType(refType RepoRefType) func(http.Handler) http.Handler {
 | 
			
		||||
	return func(next http.Handler) http.Handler {
 | 
			
		||||
		return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
			ctx := GetContext(req)
 | 
			
		||||
func RepoRefByType(refType RepoRefType) func(*Context) {
 | 
			
		||||
	return func(ctx *Context) {
 | 
			
		||||
		// Empty repository does not have reference information.
 | 
			
		||||
		if ctx.Repo.Repository.IsEmpty {
 | 
			
		||||
			return
 | 
			
		||||
@@ -851,9 +841,6 @@ func RepoRefByType(refType RepoRefType) func(http.Handler) http.Handler {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
 | 
			
		||||
 | 
			
		||||
			next.ServeHTTP(w, req)
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -85,18 +85,17 @@ func ToPullReviewCommentList(review *models.Review, doer *models.User) ([]*api.P
 | 
			
		||||
 | 
			
		||||
	apiComments := make([]*api.PullReviewComment, 0, len(review.CodeComments))
 | 
			
		||||
 | 
			
		||||
	auth := false
 | 
			
		||||
	if doer != nil {
 | 
			
		||||
		auth = doer.IsAdmin || doer.ID == review.ReviewerID
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, lines := range review.CodeComments {
 | 
			
		||||
		for _, comments := range lines {
 | 
			
		||||
			for _, comment := range comments {
 | 
			
		||||
				auth := false
 | 
			
		||||
				if doer != nil {
 | 
			
		||||
					auth = doer.IsAdmin || doer.ID == comment.Poster.ID
 | 
			
		||||
				}
 | 
			
		||||
				apiComment := &api.PullReviewComment{
 | 
			
		||||
					ID:           comment.ID,
 | 
			
		||||
					Body:         comment.Content,
 | 
			
		||||
					Reviewer:     ToUser(review.Reviewer, doer != nil, auth),
 | 
			
		||||
					Reviewer:     ToUser(comment.Poster, doer != nil, auth),
 | 
			
		||||
					ReviewID:     review.ID,
 | 
			
		||||
					Created:      comment.CreatedUnix.AsTime(),
 | 
			
		||||
					Updated:      comment.UpdatedUnix.AsTime(),
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ func GetRawDiffForFile(repoPath, startCommit, endCommit string, diffType RawDiff
 | 
			
		||||
func GetRepoRawDiffForFile(repo *Repository, startCommit, endCommit string, diffType RawDiffType, file string, writer io.Writer) error {
 | 
			
		||||
	commit, err := repo.GetCommit(endCommit)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("GetCommit: %v", err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	fileArgs := make([]string, 0)
 | 
			
		||||
	if len(file) > 0 {
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,7 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
 | 
			
		||||
 | 
			
		||||
	sizes := make(map[string]int64)
 | 
			
		||||
	err = tree.Files().ForEach(func(f *object.File) error {
 | 
			
		||||
		if f.Size == 0 || enry.IsVendor(f.Name) || enry.IsDotFile(f.Name) ||
 | 
			
		||||
		if f.Size == 0 || analyze.IsVendor(f.Name) || enry.IsDotFile(f.Name) ||
 | 
			
		||||
			enry.IsDocumentation(f.Name) || enry.IsConfiguration(f.Name) {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,7 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
 | 
			
		||||
	for _, f := range entries {
 | 
			
		||||
		contentBuf.Reset()
 | 
			
		||||
		content = contentBuf.Bytes()
 | 
			
		||||
		if f.Size() == 0 || enry.IsVendor(f.Name()) || enry.IsDotFile(f.Name()) ||
 | 
			
		||||
		if f.Size() == 0 || analyze.IsVendor(f.Name()) || enry.IsDotFile(f.Name()) ||
 | 
			
		||||
			enry.IsDocumentation(f.Name()) || enry.IsConfiguration(f.Name()) {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -68,17 +68,19 @@ func (g *Manager) start() {
 | 
			
		||||
	// Set the running state
 | 
			
		||||
	g.setState(stateRunning)
 | 
			
		||||
	if skip, _ := strconv.ParseBool(os.Getenv("SKIP_MINWINSVC")); skip {
 | 
			
		||||
		log.Trace("Skipping SVC check as SKIP_MINWINSVC is set")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Make SVC process
 | 
			
		||||
	run := svc.Run
 | 
			
		||||
	isInteractive, err := svc.IsWindowsService()
 | 
			
		||||
	isWindowsService, err := svc.IsWindowsService()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Error("Unable to ascertain if running as an Interactive Session: %v", err)
 | 
			
		||||
		log.Error("Unable to ascertain if running as an Windows Service: %v", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if isInteractive {
 | 
			
		||||
	if !isWindowsService {
 | 
			
		||||
		log.Trace("Not running a service ... using the debug SVC manager")
 | 
			
		||||
		run = debug.Run
 | 
			
		||||
	}
 | 
			
		||||
	go func() {
 | 
			
		||||
@@ -94,38 +96,49 @@ func (g *Manager) Execute(args []string, changes <-chan svc.ChangeRequest, statu
 | 
			
		||||
		status <- svc.Status{State: svc.StartPending, WaitHint: uint32(setting.StartupTimeout / time.Millisecond)}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Trace("Awaiting server start-up")
 | 
			
		||||
	// Now need to wait for everything to start...
 | 
			
		||||
	if !g.awaitServer(setting.StartupTimeout) {
 | 
			
		||||
		log.Trace("... start-up failed ... Stopped")
 | 
			
		||||
		return false, 1
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Trace("Sending Running state to SVC")
 | 
			
		||||
 | 
			
		||||
	// We need to implement some way of svc.AcceptParamChange/svc.ParamChange
 | 
			
		||||
	status <- svc.Status{
 | 
			
		||||
		State:   svc.Running,
 | 
			
		||||
		Accepts: svc.AcceptStop | svc.AcceptShutdown | acceptHammerCode,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Trace("Started")
 | 
			
		||||
 | 
			
		||||
	waitTime := 30 * time.Second
 | 
			
		||||
 | 
			
		||||
loop:
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-g.ctx.Done():
 | 
			
		||||
			log.Trace("Shutting down")
 | 
			
		||||
			g.DoGracefulShutdown()
 | 
			
		||||
			waitTime += setting.GracefulHammerTime
 | 
			
		||||
			break loop
 | 
			
		||||
		case <-g.shutdownRequested:
 | 
			
		||||
			log.Trace("Shutting down")
 | 
			
		||||
			waitTime += setting.GracefulHammerTime
 | 
			
		||||
			break loop
 | 
			
		||||
		case change := <-changes:
 | 
			
		||||
			switch change.Cmd {
 | 
			
		||||
			case svc.Interrogate:
 | 
			
		||||
				log.Trace("SVC sent interrogate")
 | 
			
		||||
				status <- change.CurrentStatus
 | 
			
		||||
			case svc.Stop, svc.Shutdown:
 | 
			
		||||
				log.Trace("SVC requested shutdown - shutting down")
 | 
			
		||||
				g.DoGracefulShutdown()
 | 
			
		||||
				waitTime += setting.GracefulHammerTime
 | 
			
		||||
				break loop
 | 
			
		||||
			case hammerCode:
 | 
			
		||||
				log.Trace("SVC requested hammer - shutting down and hammering immediately")
 | 
			
		||||
				g.DoGracefulShutdown()
 | 
			
		||||
				g.DoImmediateHammer()
 | 
			
		||||
				break loop
 | 
			
		||||
@@ -134,6 +147,8 @@ loop:
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Trace("Sending StopPending state to SVC")
 | 
			
		||||
	status <- svc.Status{
 | 
			
		||||
		State:    svc.StopPending,
 | 
			
		||||
		WaitHint: uint32(waitTime / time.Millisecond),
 | 
			
		||||
@@ -145,8 +160,10 @@ hammerLoop:
 | 
			
		||||
		case change := <-changes:
 | 
			
		||||
			switch change.Cmd {
 | 
			
		||||
			case svc.Interrogate:
 | 
			
		||||
				log.Trace("SVC sent interrogate")
 | 
			
		||||
				status <- change.CurrentStatus
 | 
			
		||||
			case svc.Stop, svc.Shutdown, hammerCmd:
 | 
			
		||||
				log.Trace("SVC requested hammer - hammering immediately")
 | 
			
		||||
				g.DoImmediateHammer()
 | 
			
		||||
				break hammerLoop
 | 
			
		||||
			default:
 | 
			
		||||
@@ -156,6 +173,8 @@ hammerLoop:
 | 
			
		||||
			break hammerLoop
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Trace("Stopped")
 | 
			
		||||
	return false, 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -178,7 +178,7 @@ func NewBleveIndexer(indexDir string) (*BleveIndexer, bool, error) {
 | 
			
		||||
 | 
			
		||||
func (b *BleveIndexer) addUpdate(batchWriter *io.PipeWriter, batchReader *bufio.Reader, commitSha string, update fileUpdate, repo *models.Repository, batch rupture.FlushingBatch) error {
 | 
			
		||||
	// Ignore vendored files in code search
 | 
			
		||||
	if setting.Indexer.ExcludeVendored && enry.IsVendor(update.Filename) {
 | 
			
		||||
	if setting.Indexer.ExcludeVendored && analyze.IsVendor(update.Filename) {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -177,7 +177,7 @@ func (b *ElasticSearchIndexer) init() (bool, error) {
 | 
			
		||||
 | 
			
		||||
func (b *ElasticSearchIndexer) addUpdate(batchWriter *io.PipeWriter, batchReader *bufio.Reader, sha string, update fileUpdate, repo *models.Repository) ([]elastic.BulkableRequest, error) {
 | 
			
		||||
	// Ignore vendored files in code search
 | 
			
		||||
	if setting.Indexer.ExcludeVendored && enry.IsVendor(update.Filename) {
 | 
			
		||||
	if setting.Indexer.ExcludeVendored && analyze.IsVendor(update.Filename) {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -44,24 +44,13 @@ type ContentStore struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get takes a Meta object and retrieves the content from the store, returning
 | 
			
		||||
// it as an io.Reader. If fromByte > 0, the reader starts from that byte
 | 
			
		||||
func (s *ContentStore) Get(meta *models.LFSMetaObject, fromByte int64) (io.ReadCloser, error) {
 | 
			
		||||
// it as an io.ReadSeekCloser.
 | 
			
		||||
func (s *ContentStore) Get(meta *models.LFSMetaObject) (storage.Object, error) {
 | 
			
		||||
	f, err := s.Open(meta.RelativePath())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Error("Whilst trying to read LFS OID[%s]: Unable to open Error: %v", meta.Oid, err)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if fromByte > 0 {
 | 
			
		||||
		if fromByte >= meta.Size {
 | 
			
		||||
			return nil, ErrRangeNotSatisfiable{
 | 
			
		||||
				FromByte: fromByte,
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		_, err = f.Seek(fromByte, io.SeekStart)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Error("Whilst trying to read LFS OID[%s]: Unable to seek to %d Error: %v", meta.Oid, fromByte, err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return f, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -74,7 +63,7 @@ func (s *ContentStore) Put(meta *models.LFSMetaObject, r io.Reader) error {
 | 
			
		||||
 | 
			
		||||
	// now pass the wrapped reader to Save - if there is a size mismatch or hash mismatch then
 | 
			
		||||
	// the errors returned by the newHashingReader should percolate up to here
 | 
			
		||||
	written, err := s.Save(p, wrappedRd)
 | 
			
		||||
	written, err := s.Save(p, wrappedRd, meta.Size)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Error("Whilst putting LFS OID[%s]: Failed to copy to tmpPath: %s Error: %v", meta.Oid, p, err)
 | 
			
		||||
		return err
 | 
			
		||||
 
 | 
			
		||||
@@ -67,5 +67,5 @@ func IsPointerFile(buf *[]byte) *models.LFSMetaObject {
 | 
			
		||||
// ReadMetaObject will read a models.LFSMetaObject and return a reader
 | 
			
		||||
func ReadMetaObject(meta *models.LFSMetaObject) (io.ReadCloser, error) {
 | 
			
		||||
	contentStore := &ContentStore{ObjectStorage: storage.LFS}
 | 
			
		||||
	return contentStore.Get(meta, 0)
 | 
			
		||||
	return contentStore.Get(meta)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -175,6 +175,11 @@ func getContentHandler(ctx *context.Context) {
 | 
			
		||||
			statusCode = 206
 | 
			
		||||
			fromByte, _ = strconv.ParseInt(match[1], 10, 32)
 | 
			
		||||
 | 
			
		||||
			if fromByte >= meta.Size {
 | 
			
		||||
				writeStatus(ctx, http.StatusRequestedRangeNotSatisfiable)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if match[2] != "" {
 | 
			
		||||
				_toByte, _ := strconv.ParseInt(match[2], 10, 32)
 | 
			
		||||
				if _toByte >= fromByte && _toByte < toByte {
 | 
			
		||||
@@ -188,18 +193,24 @@ func getContentHandler(ctx *context.Context) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	contentStore := &ContentStore{ObjectStorage: storage.LFS}
 | 
			
		||||
	content, err := contentStore.Get(meta, fromByte)
 | 
			
		||||
	content, err := contentStore.Get(meta)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if IsErrRangeNotSatisfiable(err) {
 | 
			
		||||
			writeStatus(ctx, http.StatusRequestedRangeNotSatisfiable)
 | 
			
		||||
		} else {
 | 
			
		||||
		// Errors are logged in contentStore.Get
 | 
			
		||||
			writeStatus(ctx, 404)
 | 
			
		||||
		}
 | 
			
		||||
		writeStatus(ctx, http.StatusNotFound)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer content.Close()
 | 
			
		||||
 | 
			
		||||
	if fromByte > 0 {
 | 
			
		||||
		_, err = content.Seek(fromByte, io.SeekStart)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Error("Whilst trying to read LFS OID[%s]: Unable to seek to %d Error: %v", meta.Oid, fromByte, err)
 | 
			
		||||
 | 
			
		||||
			writeStatus(ctx, http.StatusInternalServerError)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	contentLength := toByte + 1 - fromByte
 | 
			
		||||
	ctx.Resp.Header().Set("Content-Length", strconv.FormatInt(contentLength, 10))
 | 
			
		||||
	ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
 | 
			
		||||
 
 | 
			
		||||
@@ -313,7 +313,7 @@ func RenderEmoji(
 | 
			
		||||
	return ctx.postProcess(rawHTML)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var tagCleaner = regexp.MustCompile(`<((?:/?\w+/\w+)|(?:/[\w ]+/)|(/?[hH][tT][mM][lL][ />])|(/?[hH][eE][aA][dD][ />]))`)
 | 
			
		||||
var tagCleaner = regexp.MustCompile(`<((?:/?\w+/\w+)|(?:/[\w ]+/)|(/?[hH][tT][mM][lL]\b)|(/?[hH][eE][aA][dD]\b))`)
 | 
			
		||||
var nulCleaner = strings.NewReplacer("\000", "")
 | 
			
		||||
 | 
			
		||||
func (ctx *postProcessCtx) postProcess(rawHTML []byte) ([]byte, error) {
 | 
			
		||||
@@ -327,7 +327,7 @@ func (ctx *postProcessCtx) postProcess(rawHTML []byte) ([]byte, error) {
 | 
			
		||||
	_, _ = res.WriteString("<html><body>")
 | 
			
		||||
 | 
			
		||||
	// Strip out nuls - they're always invalid
 | 
			
		||||
	_, _ = nulCleaner.WriteString(res, string(tagCleaner.ReplaceAll(rawHTML, []byte("<$1"))))
 | 
			
		||||
	_, _ = res.Write(tagCleaner.ReplaceAll([]byte(nulCleaner.Replace(string(rawHTML))), []byte("<$1")))
 | 
			
		||||
 | 
			
		||||
	// close the tags
 | 
			
		||||
	_, _ = res.WriteString("</body></html>")
 | 
			
		||||
 
 | 
			
		||||
@@ -124,7 +124,7 @@ func TestRender_links(t *testing.T) {
 | 
			
		||||
		`<p><a href="http://www.example.com/wpstyle/?p=364" rel="nofollow">http://www.example.com/wpstyle/?p=364</a></p>`)
 | 
			
		||||
	test(
 | 
			
		||||
		"https://www.example.com/foo/?bar=baz&inga=42&quux",
 | 
			
		||||
		`<p><a href="https://www.example.com/foo/?bar=baz&inga=42&quux=" rel="nofollow">https://www.example.com/foo/?bar=baz&inga=42&quux</a></p>`)
 | 
			
		||||
		`<p><a href="https://www.example.com/foo/?bar=baz&inga=42&quux" rel="nofollow">https://www.example.com/foo/?bar=baz&inga=42&quux</a></p>`)
 | 
			
		||||
	test(
 | 
			
		||||
		"http://142.42.1.1/",
 | 
			
		||||
		`<p><a href="http://142.42.1.1/" rel="nofollow">http://142.42.1.1/</a></p>`)
 | 
			
		||||
 
 | 
			
		||||
@@ -46,7 +46,9 @@ func ReplaceSanitizer() {
 | 
			
		||||
	sanitizer.policy.AllowAttrs("checked", "disabled").OnElements("input")
 | 
			
		||||
 | 
			
		||||
	// Custom URL-Schemes
 | 
			
		||||
	if len(setting.Markdown.CustomURLSchemes) > 0 {
 | 
			
		||||
		sanitizer.policy.AllowURLSchemes(setting.Markdown.CustomURLSchemes...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Allow keyword markup
 | 
			
		||||
	sanitizer.policy.AllowAttrs("class").Matching(regexp.MustCompile(`^` + keywordClass + `$`)).OnElements("span")
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,8 @@
 | 
			
		||||
package markup
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"html/template"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
@@ -50,3 +52,13 @@ func Test_Sanitizer(t *testing.T) {
 | 
			
		||||
		assert.Equal(t, testCases[i+1], string(SanitizeBytes([]byte(testCases[i]))))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestSanitizeNonEscape(t *testing.T) {
 | 
			
		||||
	descStr := "<scrİpt><script>alert(document.domain)</script></scrİpt>"
 | 
			
		||||
 | 
			
		||||
	output := template.HTML(Sanitize(string(descStr)))
 | 
			
		||||
	if strings.Contains(string(output), "<script>") {
 | 
			
		||||
		t.Errorf("un-escaped <script> in output: %q", output)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -525,9 +525,6 @@ func (g *GiteaDownloader) GetPullRequests(page, perPage int) ([]*base.PullReques
 | 
			
		||||
				headRepoName = pr.Head.Repository.Name
 | 
			
		||||
				headCloneURL = pr.Head.Repository.CloneURL
 | 
			
		||||
			}
 | 
			
		||||
			if err := fixPullHeadSha(g.client, pr); err != nil {
 | 
			
		||||
				return nil, false, fmt.Errorf("error while resolving head git ref: %s for pull #%d. Error: %v", pr.Head.Ref, pr.Index, err)
 | 
			
		||||
			}
 | 
			
		||||
			headSHA = pr.Head.Sha
 | 
			
		||||
			headRef = pr.Head.Ref
 | 
			
		||||
		}
 | 
			
		||||
@@ -679,22 +676,3 @@ func (g *GiteaDownloader) GetReviews(index int64) ([]*base.Review, error) {
 | 
			
		||||
	}
 | 
			
		||||
	return allReviews, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// fixPullHeadSha is a workaround for https://github.com/go-gitea/gitea/issues/12675
 | 
			
		||||
// When no head sha is available, this is because the branch got deleted in the base repo.
 | 
			
		||||
// pr.Head.Ref points in this case not to the head repo branch name, but the base repo ref,
 | 
			
		||||
// which stays available to resolve the commit sha.
 | 
			
		||||
func fixPullHeadSha(client *gitea_sdk.Client, pr *gitea_sdk.PullRequest) error {
 | 
			
		||||
	owner := pr.Base.Repository.Owner.UserName
 | 
			
		||||
	repo := pr.Base.Repository.Name
 | 
			
		||||
	if pr.Head != nil && pr.Head.Sha == "" {
 | 
			
		||||
		refs, _, err := client.GetRepoRefs(owner, repo, pr.Head.Ref)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		} else if len(refs) == 0 {
 | 
			
		||||
			return fmt.Errorf("unable to resolve PR ref '%s'", pr.Head.Ref)
 | 
			
		||||
		}
 | 
			
		||||
		pr.Head.Sha = refs[0].Object.SHA
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -283,7 +283,7 @@ func (g *GiteaLocalUploader) CreateReleases(releases ...*base.Release) error {
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				defer rc.Close()
 | 
			
		||||
				_, err = storage.Attachments.Save(attach.RelativePath(), rc)
 | 
			
		||||
				_, err = storage.Attachments.Save(attach.RelativePath(), rc, int64(*asset.Size))
 | 
			
		||||
				return err
 | 
			
		||||
			}()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -332,7 +332,8 @@ func (a *actionNotifier) NotifyPushCommits(pusher *models.User, repo *models.Rep
 | 
			
		||||
func (a *actionNotifier) NotifyCreateRef(doer *models.User, repo *models.Repository, refType, refFullName string) {
 | 
			
		||||
	opType := models.ActionCommitRepo
 | 
			
		||||
	if refType == "tag" {
 | 
			
		||||
		opType = models.ActionPushTag
 | 
			
		||||
		// has sent same action in `NotifyPushCommits`, so skip it.
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if err := models.NotifyWatchers(&models.Action{
 | 
			
		||||
		ActUserID: doer.ID,
 | 
			
		||||
@@ -350,7 +351,8 @@ func (a *actionNotifier) NotifyCreateRef(doer *models.User, repo *models.Reposit
 | 
			
		||||
func (a *actionNotifier) NotifyDeleteRef(doer *models.User, repo *models.Repository, refType, refFullName string) {
 | 
			
		||||
	opType := models.ActionDeleteBranch
 | 
			
		||||
	if refType == "tag" {
 | 
			
		||||
		opType = models.ActionDeleteTag
 | 
			
		||||
		// has sent same action in `NotifyPushCommits`, so skip it.
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if err := models.NotifyWatchers(&models.Action{
 | 
			
		||||
		ActUserID: doer.ID,
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@ type Options struct {
 | 
			
		||||
// KnownPublicEntries list all direct children in the `public` directory
 | 
			
		||||
var KnownPublicEntries = []string{
 | 
			
		||||
	"css",
 | 
			
		||||
	"fonts",
 | 
			
		||||
	"img",
 | 
			
		||||
	"js",
 | 
			
		||||
	"serviceworker.js",
 | 
			
		||||
 
 | 
			
		||||
@@ -174,6 +174,7 @@ func (m *Manager) FlushAll(baseCtx context.Context, timeout time.Duration) error
 | 
			
		||||
		default:
 | 
			
		||||
		}
 | 
			
		||||
		mqs := m.ManagedQueues()
 | 
			
		||||
		log.Debug("Found %d Managed Queues", len(mqs))
 | 
			
		||||
		wg := sync.WaitGroup{}
 | 
			
		||||
		wg.Add(len(mqs))
 | 
			
		||||
		allEmpty := true
 | 
			
		||||
@@ -184,6 +185,7 @@ func (m *Manager) FlushAll(baseCtx context.Context, timeout time.Duration) error
 | 
			
		||||
			}
 | 
			
		||||
			allEmpty = false
 | 
			
		||||
			if flushable, ok := mq.Managed.(Flushable); ok {
 | 
			
		||||
				log.Debug("Flushing (flushable) queue: %s", mq.Name)
 | 
			
		||||
				go func(q *ManagedQueue) {
 | 
			
		||||
					localCtx, localCancel := context.WithCancel(ctx)
 | 
			
		||||
					pid := q.RegisterWorkers(1, start, hasTimeout, end, localCancel, true)
 | 
			
		||||
@@ -196,7 +198,11 @@ func (m *Manager) FlushAll(baseCtx context.Context, timeout time.Duration) error
 | 
			
		||||
					wg.Done()
 | 
			
		||||
				}(mq)
 | 
			
		||||
			} else {
 | 
			
		||||
				log.Debug("Queue: %s is non-empty but is not flushable - adding 100 millisecond wait", mq.Name)
 | 
			
		||||
				go func() {
 | 
			
		||||
					<-time.After(100 * time.Millisecond)
 | 
			
		||||
					wg.Done()
 | 
			
		||||
				}()
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -99,42 +99,10 @@ func UploadRepoFiles(repo *models.Repository, doer *models.User, opts *UploadRep
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Copy uploaded files into repository.
 | 
			
		||||
	for i, uploadInfo := range infos {
 | 
			
		||||
		file, err := os.Open(uploadInfo.upload.LocalPath())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
	for i := range infos {
 | 
			
		||||
		if err := copyUploadedLFSFileIntoRepository(&infos[i], filename2attribute2info, t, opts.TreePath); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		defer file.Close()
 | 
			
		||||
 | 
			
		||||
		var objectHash string
 | 
			
		||||
		if setting.LFS.StartServer && filename2attribute2info[uploadInfo.upload.Name] != nil && filename2attribute2info[uploadInfo.upload.Name]["filter"] == "lfs" {
 | 
			
		||||
			// Handle LFS
 | 
			
		||||
			// FIXME: Inefficient! this should probably happen in models.Upload
 | 
			
		||||
			oid, err := models.GenerateLFSOid(file)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			fileInfo, err := file.Stat()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			uploadInfo.lfsMetaObject = &models.LFSMetaObject{Oid: oid, Size: fileInfo.Size(), RepositoryID: t.repo.ID}
 | 
			
		||||
 | 
			
		||||
			if objectHash, err = t.HashObject(strings.NewReader(uploadInfo.lfsMetaObject.Pointer())); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			infos[i] = uploadInfo
 | 
			
		||||
 | 
			
		||||
		} else if objectHash, err = t.HashObject(file); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Add the object to the index
 | 
			
		||||
		if err := t.AddObjectToIndex("100644", objectHash, path.Join(opts.TreePath, uploadInfo.upload.Name)); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Now write the tree
 | 
			
		||||
@@ -154,11 +122,11 @@ func UploadRepoFiles(repo *models.Repository, doer *models.User, opts *UploadRep
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Now deal with LFS objects
 | 
			
		||||
	for _, uploadInfo := range infos {
 | 
			
		||||
		if uploadInfo.lfsMetaObject == nil {
 | 
			
		||||
	for i := range infos {
 | 
			
		||||
		if infos[i].lfsMetaObject == nil {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		uploadInfo.lfsMetaObject, err = models.NewLFSMetaObject(uploadInfo.lfsMetaObject)
 | 
			
		||||
		infos[i].lfsMetaObject, err = models.NewLFSMetaObject(infos[i].lfsMetaObject)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			// OK Now we need to cleanup
 | 
			
		||||
			return cleanUpAfterFailure(&infos, t, err)
 | 
			
		||||
@@ -170,28 +138,10 @@ func UploadRepoFiles(repo *models.Repository, doer *models.User, opts *UploadRep
 | 
			
		||||
	// OK now we can insert the data into the store - there's no way to clean up the store
 | 
			
		||||
	// once it's in there, it's in there.
 | 
			
		||||
	contentStore := &lfs.ContentStore{ObjectStorage: storage.LFS}
 | 
			
		||||
	for _, uploadInfo := range infos {
 | 
			
		||||
		if uploadInfo.lfsMetaObject == nil {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		exist, err := contentStore.Exists(uploadInfo.lfsMetaObject)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
	for _, info := range infos {
 | 
			
		||||
		if err := uploadToLFSContentStore(info, contentStore); err != nil {
 | 
			
		||||
			return cleanUpAfterFailure(&infos, t, err)
 | 
			
		||||
		}
 | 
			
		||||
		if !exist {
 | 
			
		||||
			file, err := os.Open(uploadInfo.upload.LocalPath())
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return cleanUpAfterFailure(&infos, t, err)
 | 
			
		||||
			}
 | 
			
		||||
			defer file.Close()
 | 
			
		||||
			// FIXME: Put regenerates the hash and copies the file over.
 | 
			
		||||
			// I guess this strictly ensures the soundness of the store but this is inefficient.
 | 
			
		||||
			if err := contentStore.Put(uploadInfo.lfsMetaObject, file); err != nil {
 | 
			
		||||
				// OK Now we need to cleanup
 | 
			
		||||
				// Can't clean up the store, once uploaded there they're there.
 | 
			
		||||
				return cleanUpAfterFailure(&infos, t, err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Then push this tree to NewBranch
 | 
			
		||||
@@ -201,3 +151,62 @@ func UploadRepoFiles(repo *models.Repository, doer *models.User, opts *UploadRep
 | 
			
		||||
 | 
			
		||||
	return models.DeleteUploads(uploads...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func copyUploadedLFSFileIntoRepository(info *uploadInfo, filename2attribute2info map[string]map[string]string, t *TemporaryUploadRepository, treePath string) error {
 | 
			
		||||
	file, err := os.Open(info.upload.LocalPath())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer file.Close()
 | 
			
		||||
 | 
			
		||||
	var objectHash string
 | 
			
		||||
	if setting.LFS.StartServer && filename2attribute2info[info.upload.Name] != nil && filename2attribute2info[info.upload.Name]["filter"] == "lfs" {
 | 
			
		||||
		// Handle LFS
 | 
			
		||||
		// FIXME: Inefficient! this should probably happen in models.Upload
 | 
			
		||||
		oid, err := models.GenerateLFSOid(file)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		fileInfo, err := file.Stat()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		info.lfsMetaObject = &models.LFSMetaObject{Oid: oid, Size: fileInfo.Size(), RepositoryID: t.repo.ID}
 | 
			
		||||
 | 
			
		||||
		if objectHash, err = t.HashObject(strings.NewReader(info.lfsMetaObject.Pointer())); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	} else if objectHash, err = t.HashObject(file); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Add the object to the index
 | 
			
		||||
	return t.AddObjectToIndex("100644", objectHash, path.Join(treePath, info.upload.Name))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func uploadToLFSContentStore(info uploadInfo, contentStore *lfs.ContentStore) error {
 | 
			
		||||
	if info.lfsMetaObject == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	exist, err := contentStore.Exists(info.lfsMetaObject)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if !exist {
 | 
			
		||||
		file, err := os.Open(info.upload.LocalPath())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		defer file.Close()
 | 
			
		||||
		// FIXME: Put regenerates the hash and copies the file over.
 | 
			
		||||
		// I guess this strictly ensures the soundness of the store but this is inefficient.
 | 
			
		||||
		if err := contentStore.Put(info.lfsMetaObject, file); err != nil {
 | 
			
		||||
			// OK Now we need to cleanup
 | 
			
		||||
			// Can't clean up the store, once uploaded there they're there.
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -66,7 +66,7 @@ func (l *LocalStorage) Open(path string) (Object, error) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Save a file
 | 
			
		||||
func (l *LocalStorage) Save(path string, r io.Reader) (int64, error) {
 | 
			
		||||
func (l *LocalStorage) Save(path string, r io.Reader, size int64) (int64, error) {
 | 
			
		||||
	p := filepath.Join(l.dir, path)
 | 
			
		||||
	if err := os.MkdirAll(filepath.Dir(p), os.ModePerm); err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
 
 | 
			
		||||
@@ -131,13 +131,13 @@ func (m *MinioStorage) Open(path string) (Object, error) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Save save a file to minio
 | 
			
		||||
func (m *MinioStorage) Save(path string, r io.Reader) (int64, error) {
 | 
			
		||||
func (m *MinioStorage) Save(path string, r io.Reader, size int64) (int64, error) {
 | 
			
		||||
	uploadInfo, err := m.client.PutObject(
 | 
			
		||||
		m.ctx,
 | 
			
		||||
		m.bucket,
 | 
			
		||||
		m.buildMinioPath(path),
 | 
			
		||||
		r,
 | 
			
		||||
		-1,
 | 
			
		||||
		size,
 | 
			
		||||
		minio.PutObjectOptions{ContentType: "application/octet-stream"},
 | 
			
		||||
	)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,8 @@ type Object interface {
 | 
			
		||||
// ObjectStorage represents an object storage to handle a bucket and files
 | 
			
		||||
type ObjectStorage interface {
 | 
			
		||||
	Open(path string) (Object, error)
 | 
			
		||||
	Save(path string, r io.Reader) (int64, error)
 | 
			
		||||
	// Save store a object, if size is unknown set -1
 | 
			
		||||
	Save(path string, r io.Reader, size int64) (int64, error)
 | 
			
		||||
	Stat(path string) (os.FileInfo, error)
 | 
			
		||||
	Delete(path string) error
 | 
			
		||||
	URL(path, name string) (*url.URL, error)
 | 
			
		||||
@@ -80,7 +81,13 @@ func Copy(dstStorage ObjectStorage, dstPath string, srcStorage ObjectStorage, sr
 | 
			
		||||
	}
 | 
			
		||||
	defer f.Close()
 | 
			
		||||
 | 
			
		||||
	return dstStorage.Save(dstPath, f)
 | 
			
		||||
	size := int64(-1)
 | 
			
		||||
	fsinfo, err := f.Stat()
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		size = fsinfo.Size()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return dstStorage.Save(dstPath, f, size)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SaveFrom saves data to the ObjectStorage with path p from the callback
 | 
			
		||||
@@ -94,7 +101,7 @@ func SaveFrom(objStorage ObjectStorage, p string, callback func(w io.Writer) err
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	_, err := objStorage.Save(p, pr)
 | 
			
		||||
	_, err := objStorage.Save(p, pr, -1)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -68,10 +68,11 @@ func Wrap(handlers ...interface{}) http.HandlerFunc {
 | 
			
		||||
				}
 | 
			
		||||
			case func(http.Handler) http.Handler:
 | 
			
		||||
				var next = http.HandlerFunc(func(http.ResponseWriter, *http.Request) {})
 | 
			
		||||
				t(next).ServeHTTP(resp, req)
 | 
			
		||||
				if r, ok := resp.(context.ResponseWriter); ok && r.Status() > 0 {
 | 
			
		||||
					return
 | 
			
		||||
				if len(handlers) > i+1 {
 | 
			
		||||
					next = Wrap(handlers[i+1:]...)
 | 
			
		||||
				}
 | 
			
		||||
				t(next).ServeHTTP(resp, req)
 | 
			
		||||
				return
 | 
			
		||||
			default:
 | 
			
		||||
				panic(fmt.Sprintf("Unsupported handler type: %#v", t))
 | 
			
		||||
			}
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,6 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/modules/context"
 | 
			
		||||
	"code.gitea.io/gitea/modules/convert"
 | 
			
		||||
	issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
 | 
			
		||||
	"code.gitea.io/gitea/modules/log"
 | 
			
		||||
	"code.gitea.io/gitea/modules/notification"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	api "code.gitea.io/gitea/modules/structs"
 | 
			
		||||
@@ -113,11 +112,7 @@ func SearchIssues(ctx *context.APIContext) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// find repos user can access (for issue search)
 | 
			
		||||
	repoIDs := make([]int64, 0)
 | 
			
		||||
	opts := &models.SearchRepoOptions{
 | 
			
		||||
		ListOptions: models.ListOptions{
 | 
			
		||||
			PageSize: 15,
 | 
			
		||||
		},
 | 
			
		||||
		Private:     false,
 | 
			
		||||
		AllPublic:   true,
 | 
			
		||||
		TopicOnly:   false,
 | 
			
		||||
@@ -132,23 +127,12 @@ func SearchIssues(ctx *context.APIContext) {
 | 
			
		||||
		opts.AllLimited = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for page := 1; ; page++ {
 | 
			
		||||
		opts.Page = page
 | 
			
		||||
		repos, count, err := models.SearchRepositoryByName(opts)
 | 
			
		||||
	repoIDs, _, err := models.SearchRepositoryIDs(opts)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.Error(http.StatusInternalServerError, "SearchRepositoryByName", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		if len(repos) == 0 {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		log.Trace("Processing next %d repos of %d", len(repos), count)
 | 
			
		||||
		for _, repo := range repos {
 | 
			
		||||
			repoIDs = append(repoIDs, repo.ID)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var issues []*models.Issue
 | 
			
		||||
	var filteredCount int64
 | 
			
		||||
 | 
			
		||||
@@ -157,7 +141,6 @@ func SearchIssues(ctx *context.APIContext) {
 | 
			
		||||
		keyword = ""
 | 
			
		||||
	}
 | 
			
		||||
	var issueIDs []int64
 | 
			
		||||
	var labelIDs []int64
 | 
			
		||||
	if len(keyword) > 0 && len(repoIDs) > 0 {
 | 
			
		||||
		if issueIDs, err = issue_indexer.SearchIssuesByKeyword(repoIDs, keyword); err != nil {
 | 
			
		||||
			ctx.Error(http.StatusInternalServerError, "SearchIssuesByKeyword", err)
 | 
			
		||||
@@ -192,7 +175,7 @@ func SearchIssues(ctx *context.APIContext) {
 | 
			
		||||
 | 
			
		||||
	// Only fetch the issues if we either don't have a keyword or the search returned issues
 | 
			
		||||
	// This would otherwise return all issues if no issues were found by the search.
 | 
			
		||||
	if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 {
 | 
			
		||||
	if len(keyword) == 0 || len(issueIDs) > 0 || len(includedLabelNames) > 0 {
 | 
			
		||||
		issuesOpt := &models.IssuesOptions{
 | 
			
		||||
			ListOptions: models.ListOptions{
 | 
			
		||||
				Page:     ctx.QueryInt("page"),
 | 
			
		||||
 
 | 
			
		||||
@@ -274,7 +274,11 @@ func DeleteOauth2Application(ctx *context.APIContext) {
 | 
			
		||||
	//     "$ref": "#/responses/empty"
 | 
			
		||||
	appID := ctx.ParamsInt64(":id")
 | 
			
		||||
	if err := models.DeleteOAuth2Application(appID, ctx.User.ID); err != nil {
 | 
			
		||||
		if models.IsErrOAuthApplicationNotFound(err) {
 | 
			
		||||
			ctx.NotFound()
 | 
			
		||||
		} else {
 | 
			
		||||
			ctx.Error(http.StatusInternalServerError, "DeleteOauth2ApplicationByID", err)
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,17 @@ func Events(ctx *context.Context) {
 | 
			
		||||
	ctx.Resp.Header().Set("X-Accel-Buffering", "no")
 | 
			
		||||
	ctx.Resp.WriteHeader(http.StatusOK)
 | 
			
		||||
 | 
			
		||||
	if !ctx.IsSigned {
 | 
			
		||||
		// Return unauthorized status event
 | 
			
		||||
		event := (&eventsource.Event{
 | 
			
		||||
			Name: "close",
 | 
			
		||||
			Data: "unauthorized",
 | 
			
		||||
		})
 | 
			
		||||
		_, _ = event.WriteTo(ctx)
 | 
			
		||||
		ctx.Resp.Flush()
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Listen to connection close and un-register messageChan
 | 
			
		||||
	notify := ctx.Req.Context().Done()
 | 
			
		||||
	ctx.Resp.Flush()
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@
 | 
			
		||||
package repo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"path"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
@@ -389,6 +390,11 @@ func RawDiff(ctx *context.Context) {
 | 
			
		||||
		git.RawDiffType(ctx.Params(":ext")),
 | 
			
		||||
		ctx.Resp,
 | 
			
		||||
	); err != nil {
 | 
			
		||||
		if git.IsErrNotExist(err) {
 | 
			
		||||
			ctx.NotFound("GetRawDiff",
 | 
			
		||||
				errors.New("commit "+ctx.Params(":sha")+" does not exist."))
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		ctx.ServerError("GetRawDiff", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -431,11 +431,15 @@ func PrepareCompareDiff(
 | 
			
		||||
		ctx.Data["IsNothingToCompare"] = true
 | 
			
		||||
		if unit, err := repo.GetUnit(models.UnitTypePullRequests); err == nil {
 | 
			
		||||
			config := unit.PullRequestsConfig()
 | 
			
		||||
 | 
			
		||||
			if !config.AutodetectManualMerge {
 | 
			
		||||
				ctx.Data["AllowEmptyPr"] = !(baseBranch == headBranch && ctx.Repo.Repository.Name == headRepo.Name)
 | 
			
		||||
			} else {
 | 
			
		||||
				ctx.Data["AllowEmptyPr"] = false
 | 
			
		||||
				allowEmptyPr := !(baseBranch == headBranch && ctx.Repo.Repository.Name == headRepo.Name)
 | 
			
		||||
				ctx.Data["AllowEmptyPr"] = allowEmptyPr
 | 
			
		||||
 | 
			
		||||
				return !allowEmptyPr
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			ctx.Data["AllowEmptyPr"] = false
 | 
			
		||||
		}
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -192,6 +192,9 @@ func CreatePost(ctx *context.Context) {
 | 
			
		||||
	ctx.Data["Licenses"] = models.Licenses
 | 
			
		||||
	ctx.Data["Readmes"] = models.Readmes
 | 
			
		||||
 | 
			
		||||
	ctx.Data["CanCreateRepo"] = ctx.User.CanCreateRepo()
 | 
			
		||||
	ctx.Data["MaxCreationLimit"] = ctx.User.MaxCreationLimit()
 | 
			
		||||
 | 
			
		||||
	ctxUser := checkContextUser(ctx, form.UID)
 | 
			
		||||
	if ctx.Written() {
 | 
			
		||||
		return
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@ import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
@@ -87,13 +88,21 @@ func storageHandler(storageSetting setting.Storage, prefix string, objStore stor
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if !strings.HasPrefix(req.URL.RequestURI(), "/"+prefix) {
 | 
			
		||||
			prefix := strings.Trim(prefix, "/")
 | 
			
		||||
 | 
			
		||||
			if !strings.HasPrefix(req.URL.EscapedPath(), "/"+prefix+"/") {
 | 
			
		||||
				next.ServeHTTP(w, req)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			rPath := strings.TrimPrefix(req.URL.RequestURI(), "/"+prefix)
 | 
			
		||||
			rPath := strings.TrimPrefix(req.URL.EscapedPath(), "/"+prefix+"/")
 | 
			
		||||
			rPath = strings.TrimPrefix(rPath, "/")
 | 
			
		||||
			if rPath == "" {
 | 
			
		||||
				http.Error(w, "file not found", 404)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			rPath = path.Clean("/" + filepath.ToSlash(rPath))
 | 
			
		||||
			rPath = rPath[1:]
 | 
			
		||||
 | 
			
		||||
			fi, err := objStore.Stat(rPath)
 | 
			
		||||
			if err == nil && httpcache.HandleTimeCache(req, w, fi) {
 | 
			
		||||
 
 | 
			
		||||
@@ -168,15 +168,6 @@ func WebRoutes() *web.Route {
 | 
			
		||||
		r.Use(h)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (setting.Protocol == setting.FCGI || setting.Protocol == setting.FCGIUnix) && setting.AppSubURL != "" {
 | 
			
		||||
		r.Use(func(next http.Handler) http.Handler {
 | 
			
		||||
			return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
 | 
			
		||||
				req.URL.Path = strings.TrimPrefix(req.URL.Path, setting.AppSubURL)
 | 
			
		||||
				next.ServeHTTP(resp, req)
 | 
			
		||||
			})
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mailer.InitMailRender(templates.Mailer())
 | 
			
		||||
 | 
			
		||||
	if setting.Service.EnableCaptcha {
 | 
			
		||||
@@ -400,7 +391,7 @@ func RegisterRoutes(m *web.Route) {
 | 
			
		||||
		})
 | 
			
		||||
	}, reqSignOut)
 | 
			
		||||
 | 
			
		||||
	m.Any("/user/events", reqSignIn, events.Events)
 | 
			
		||||
	m.Any("/user/events", events.Events)
 | 
			
		||||
 | 
			
		||||
	m.Group("/login/oauth", func() {
 | 
			
		||||
		m.Get("/authorize", bindIgnErr(auth.AuthorizationForm{}), user.AuthorizeOAuth)
 | 
			
		||||
@@ -700,7 +691,7 @@ func RegisterRoutes(m *web.Route) {
 | 
			
		||||
	}, reqSignIn)
 | 
			
		||||
 | 
			
		||||
	// ***** Release Attachment Download without Signin
 | 
			
		||||
	m.Get("/{username}/{reponame}/releases/download/{vTag}/{fileName}", ignSignIn, context.RepoAssignment(), repo.MustBeNotEmpty, repo.RedirectDownload)
 | 
			
		||||
	m.Get("/{username}/{reponame}/releases/download/{vTag}/{fileName}", ignSignIn, context.RepoAssignment, repo.MustBeNotEmpty, repo.RedirectDownload)
 | 
			
		||||
 | 
			
		||||
	m.Group("/{username}/{reponame}", func() {
 | 
			
		||||
		m.Group("/settings", func() {
 | 
			
		||||
@@ -780,9 +771,9 @@ func RegisterRoutes(m *web.Route) {
 | 
			
		||||
			ctx.Data["PageIsSettings"] = true
 | 
			
		||||
			ctx.Data["LFSStartServer"] = setting.LFS.StartServer
 | 
			
		||||
		})
 | 
			
		||||
	}, reqSignIn, context.RepoAssignment(), context.UnitTypes(), reqRepoAdmin, context.RepoRef())
 | 
			
		||||
	}, reqSignIn, context.RepoAssignment, context.UnitTypes(), reqRepoAdmin, context.RepoRef())
 | 
			
		||||
 | 
			
		||||
	m.Post("/{username}/{reponame}/action/{action}", reqSignIn, context.RepoAssignment(), context.UnitTypes(), repo.Action)
 | 
			
		||||
	m.Post("/{username}/{reponame}/action/{action}", reqSignIn, context.RepoAssignment, context.UnitTypes(), repo.Action)
 | 
			
		||||
 | 
			
		||||
	// Grouping for those endpoints not requiring authentication
 | 
			
		||||
	m.Group("/{username}/{reponame}", func() {
 | 
			
		||||
@@ -792,7 +783,7 @@ func RegisterRoutes(m *web.Route) {
 | 
			
		||||
		m.Combo("/compare/*", repo.MustBeNotEmpty, reqRepoCodeReader, repo.SetEditorconfigIfExists).
 | 
			
		||||
			Get(ignSignIn, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.CompareDiff).
 | 
			
		||||
			Post(reqSignIn, context.RepoMustNotBeArchived(), reqRepoPullsReader, repo.MustAllowPulls, bindIgnErr(auth.CreateIssueForm{}), repo.SetWhitespaceBehavior, repo.CompareAndPullRequestPost)
 | 
			
		||||
	}, context.RepoAssignment(), context.UnitTypes())
 | 
			
		||||
	}, context.RepoAssignment, context.UnitTypes())
 | 
			
		||||
 | 
			
		||||
	// Grouping for those endpoints that do require authentication
 | 
			
		||||
	m.Group("/{username}/{reponame}", func() {
 | 
			
		||||
@@ -899,7 +890,7 @@ func RegisterRoutes(m *web.Route) {
 | 
			
		||||
			m.Post("/restore", repo.RestoreBranchPost)
 | 
			
		||||
		}, context.RepoMustNotBeArchived(), reqRepoCodeWriter, repo.MustBeNotEmpty)
 | 
			
		||||
 | 
			
		||||
	}, reqSignIn, context.RepoAssignment(), context.UnitTypes())
 | 
			
		||||
	}, reqSignIn, context.RepoAssignment, context.UnitTypes())
 | 
			
		||||
 | 
			
		||||
	// Releases
 | 
			
		||||
	m.Group("/{username}/{reponame}", func() {
 | 
			
		||||
@@ -937,11 +928,11 @@ func RegisterRoutes(m *web.Route) {
 | 
			
		||||
			}
 | 
			
		||||
			ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
 | 
			
		||||
		})
 | 
			
		||||
	}, ignSignIn, context.RepoAssignment(), context.UnitTypes(), reqRepoReleaseReader)
 | 
			
		||||
	}, ignSignIn, context.RepoAssignment, context.UnitTypes(), reqRepoReleaseReader)
 | 
			
		||||
 | 
			
		||||
	m.Group("/{username}/{reponame}", func() {
 | 
			
		||||
		m.Post("/topics", repo.TopicsPost)
 | 
			
		||||
	}, context.RepoAssignment(), context.RepoMustNotBeArchived(), reqRepoAdmin)
 | 
			
		||||
	}, context.RepoAssignment, context.RepoMustNotBeArchived(), reqRepoAdmin)
 | 
			
		||||
 | 
			
		||||
	m.Group("/{username}/{reponame}", func() {
 | 
			
		||||
		m.Group("", func() {
 | 
			
		||||
@@ -1089,17 +1080,17 @@ func RegisterRoutes(m *web.Route) {
 | 
			
		||||
		}, context.RepoRef(), reqRepoCodeReader)
 | 
			
		||||
		m.Get("/commit/{sha:([a-f0-9]{7,40})}.{ext:patch|diff}",
 | 
			
		||||
			repo.MustBeNotEmpty, reqRepoCodeReader, repo.RawDiff)
 | 
			
		||||
	}, ignSignIn, context.RepoAssignment(), context.UnitTypes())
 | 
			
		||||
	}, ignSignIn, context.RepoAssignment, context.UnitTypes())
 | 
			
		||||
	m.Group("/{username}/{reponame}", func() {
 | 
			
		||||
		m.Get("/stars", repo.Stars)
 | 
			
		||||
		m.Get("/watchers", repo.Watchers)
 | 
			
		||||
		m.Get("/search", reqRepoCodeReader, repo.Search)
 | 
			
		||||
	}, ignSignIn, context.RepoAssignment(), context.RepoRef(), context.UnitTypes())
 | 
			
		||||
	}, ignSignIn, context.RepoAssignment, context.RepoRef(), context.UnitTypes())
 | 
			
		||||
 | 
			
		||||
	m.Group("/{username}", func() {
 | 
			
		||||
		m.Group("/{reponame}", func() {
 | 
			
		||||
			m.Get("", repo.SetEditorconfigIfExists, repo.Home)
 | 
			
		||||
		}, goGet, ignSignIn, context.RepoAssignment(), context.RepoRef(), context.UnitTypes())
 | 
			
		||||
		}, goGet, ignSignIn, context.RepoAssignment, context.RepoRef(), context.UnitTypes())
 | 
			
		||||
 | 
			
		||||
		m.Group("/{reponame}", func() {
 | 
			
		||||
			m.Group("/info/lfs", func() {
 | 
			
		||||
 
 | 
			
		||||
@@ -1014,6 +1014,11 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
 | 
			
		||||
			}
 | 
			
		||||
			diffLine := &DiffLine{Type: DiffLineAdd, RightIdx: rightLine}
 | 
			
		||||
			rightLine++
 | 
			
		||||
			if curSection == nil {
 | 
			
		||||
				// Create a new section to represent this hunk
 | 
			
		||||
				curSection = &DiffSection{}
 | 
			
		||||
				curFile.Sections = append(curFile.Sections, curSection)
 | 
			
		||||
			}
 | 
			
		||||
			curSection.Lines = append(curSection.Lines, diffLine)
 | 
			
		||||
		case '-':
 | 
			
		||||
			curFileLinesCount++
 | 
			
		||||
@@ -1026,6 +1031,11 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
 | 
			
		||||
			if leftLine > 0 {
 | 
			
		||||
				leftLine++
 | 
			
		||||
			}
 | 
			
		||||
			if curSection == nil {
 | 
			
		||||
				// Create a new section to represent this hunk
 | 
			
		||||
				curSection = &DiffSection{}
 | 
			
		||||
				curFile.Sections = append(curFile.Sections, curSection)
 | 
			
		||||
			}
 | 
			
		||||
			curSection.Lines = append(curSection.Lines, diffLine)
 | 
			
		||||
		case ' ':
 | 
			
		||||
			curFileLinesCount++
 | 
			
		||||
@@ -1036,6 +1046,11 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
 | 
			
		||||
			diffLine := &DiffLine{Type: DiffLinePlain, LeftIdx: leftLine, RightIdx: rightLine}
 | 
			
		||||
			leftLine++
 | 
			
		||||
			rightLine++
 | 
			
		||||
			if curSection == nil {
 | 
			
		||||
				// Create a new section to represent this hunk
 | 
			
		||||
				curSection = &DiffSection{}
 | 
			
		||||
				curFile.Sections = append(curFile.Sections, curSection)
 | 
			
		||||
			}
 | 
			
		||||
			curSection.Lines = append(curSection.Lines, diffLine)
 | 
			
		||||
		default:
 | 
			
		||||
			// This is unexpected
 | 
			
		||||
@@ -1288,6 +1303,14 @@ func CommentAsDiff(c *models.Comment) (*Diff, error) {
 | 
			
		||||
 | 
			
		||||
// CommentMustAsDiff executes AsDiff and logs the error instead of returning
 | 
			
		||||
func CommentMustAsDiff(c *models.Comment) *Diff {
 | 
			
		||||
	if c == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if err := recover(); err != nil {
 | 
			
		||||
			log.Error("PANIC whilst retrieving diff for comment[%d] Error: %v\nStack: %s", c.ID, err, log.Stack(2))
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
	diff, err := CommentAsDiff(c)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Warn("CommentMustAsDiff: %v", err)
 | 
			
		||||
 
 | 
			
		||||
@@ -64,7 +64,7 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
 | 
			
		||||
	pr.Merger = doer
 | 
			
		||||
	pr.MergerID = doer.ID
 | 
			
		||||
 | 
			
		||||
	if _, err = pr.SetMerged(); err != nil {
 | 
			
		||||
	if _, err := pr.SetMerged(); err != nil {
 | 
			
		||||
		log.Error("setMerged [%d]: %v", pr.ID, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@
 | 
			
		||||
            <div class="twelve wide field">
 | 
			
		||||
                <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." autofocus>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="two wide field">
 | 
			
		||||
            <div class="two wide field mx-2">
 | 
			
		||||
                <select name="t">
 | 
			
		||||
                    <option value="">{{.i18n.Tr "explore.search.fuzzy"}}</option>
 | 
			
		||||
                    <option value="match" {{if eq .queryType "match"}}selected{{end}}>{{.i18n.Tr "explore.search.match"}}</option>
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@
 | 
			
		||||
						</td>
 | 
			
		||||
						<td class="right aligned overflow-visible">
 | 
			
		||||
							<div class="ui basic jump dropdown icon button poping up" data-content="{{$.i18n.Tr "repo.branch.download" ($.DefaultBranch)}}" data-variation="tiny inverted" data-position="top right">
 | 
			
		||||
							  <i class="download icon"></i>
 | 
			
		||||
							  {{svg "octicon-download"}}
 | 
			
		||||
							  <div class="menu">
 | 
			
		||||
							    <a class="item archive-link" data-url="{{$.RepoLink}}/archive/{{EscapePound $.DefaultBranch}}.zip">{{svg "octicon-file-zip"}} ZIP</a>
 | 
			
		||||
							    <a class="item archive-link" data-url="{{$.RepoLink}}/archive/{{EscapePound $.DefaultBranch}}.tar.gz">{{svg "octicon-file-zip"}} TAR.GZ</a>
 | 
			
		||||
@@ -91,20 +91,20 @@
 | 
			
		||||
											</a>
 | 
			
		||||
											{{end}}
 | 
			
		||||
										{{else}}
 | 
			
		||||
											<a href="{{.LatestPullRequest.Issue.HTMLURL}}">{{if not .LatestPullRequest.IsSameRepo}}{{.LatestPullRequest.BaseRepo.FullName}}{{end}}#{{.LatestPullRequest.Issue.Index}}</a>
 | 
			
		||||
											<a href="{{.LatestPullRequest.Issue.HTMLURL}}" class="vm">{{if not .LatestPullRequest.IsSameRepo}}{{.LatestPullRequest.BaseRepo.FullName}}{{end}}#{{.LatestPullRequest.Issue.Index}}</a>
 | 
			
		||||
											{{if .LatestPullRequest.HasMerged}}
 | 
			
		||||
												<a href="{{.LatestPullRequest.Issue.HTMLURL}}" class="ui text-label purple mini label">{{svg "octicon-git-merge"}} {{$.i18n.Tr "repo.pulls.merged"}}</a>
 | 
			
		||||
												<a href="{{.LatestPullRequest.Issue.HTMLURL}}" class="ui text-label purple large label vm">{{svg "octicon-git-merge" 16 "mr-2"}}{{$.i18n.Tr "repo.pulls.merged"}}</a>
 | 
			
		||||
											{{else if .LatestPullRequest.Issue.IsClosed}}
 | 
			
		||||
												<a href="{{.LatestPullRequest.Issue.HTMLURL}}" class="ui text-label red mini label">{{svg "octicon-git-pull-request"}} {{$.i18n.Tr "repo.issues.closed_title"}}</a>
 | 
			
		||||
												<a href="{{.LatestPullRequest.Issue.HTMLURL}}" class="ui text-label red large label vm">{{svg "octicon-git-pull-request" 16 "mr-2"}}{{$.i18n.Tr "repo.issues.closed_title"}}</a>
 | 
			
		||||
											{{else}}
 | 
			
		||||
												<a href="{{.LatestPullRequest.Issue.HTMLURL}}" class="ui text-label green mini label">{{svg "octicon-git-pull-request"}} {{$.i18n.Tr "repo.issues.open_title"}}</a>
 | 
			
		||||
												<a href="{{.LatestPullRequest.Issue.HTMLURL}}" class="ui text-label green large label vm">{{svg "octicon-git-pull-request" 16 "mr-2"}}{{$.i18n.Tr "repo.issues.open_title"}}</a>
 | 
			
		||||
											{{end}}
 | 
			
		||||
										{{end}}
 | 
			
		||||
									</td>
 | 
			
		||||
									<td class="two wide right aligned overflow-visible">
 | 
			
		||||
										{{if (not .IsDeleted)}}
 | 
			
		||||
											<div class="ui basic jump dropdown icon button poping up" data-content="{{$.i18n.Tr "repo.branch.download" (.Name)}}" data-variation="tiny inverted" data-position="top right">
 | 
			
		||||
												<i class="download icon"></i>
 | 
			
		||||
												{{svg "octicon-download"}}
 | 
			
		||||
												<div class="menu">
 | 
			
		||||
													<a class="item archive-link" data-url="{{$.RepoLink}}/archive/{{EscapePound .Name}}.zip">{{svg "octicon-file-zip"}} ZIP</a>
 | 
			
		||||
													<a class="item archive-link" data-url="{{$.RepoLink}}/archive/{{EscapePound .Name}}.tar.gz">{{svg "octicon-file-zip"}} TAR.GZ</a>
 | 
			
		||||
 
 | 
			
		||||
@@ -43,15 +43,13 @@
 | 
			
		||||
		</ol>
 | 
			
		||||
		{{range $i, $file := .Diff.Files}}
 | 
			
		||||
			{{if $file.IsIncomplete}}
 | 
			
		||||
				<div class="diff-file-box diff-box file-content">
 | 
			
		||||
				<div class="diff-file-box diff-box file-content mt-3">
 | 
			
		||||
					<h4 class="ui top attached normal header rounded">
 | 
			
		||||
						<a role="button" class="fold-file muted mr-2">
 | 
			
		||||
							{{svg "octicon-chevron-down" 18}}
 | 
			
		||||
						</a>
 | 
			
		||||
						<div class="bold ui left df ac">
 | 
			
		||||
							{{if not $file.IsRenamed}}
 | 
			
		||||
							{{template "repo/diff/stats" dict "file" . "root" $}}
 | 
			
		||||
							{{end}}
 | 
			
		||||
						</div>
 | 
			
		||||
						<span class="file mono">{{$file.Name}}</span>
 | 
			
		||||
						<div class="diff-file-header-actions df ac">
 | 
			
		||||
@@ -70,7 +68,7 @@
 | 
			
		||||
					</h4>
 | 
			
		||||
				</div>
 | 
			
		||||
			{{else}}
 | 
			
		||||
				<div class="diff-file-box diff-box file-content {{TabSizeClass $.Editorconfig $file.Name}}" id="diff-{{.Index}}">
 | 
			
		||||
				<div class="diff-file-box diff-box file-content {{TabSizeClass $.Editorconfig $file.Name}} mt-3" id="diff-{{.Index}}">
 | 
			
		||||
					<h4 class="diff-file-header sticky-2nd-row ui top attached normal header df ac sb">
 | 
			
		||||
						<div class="df ac">
 | 
			
		||||
							{{$isImage := false}}
 | 
			
		||||
@@ -85,7 +83,7 @@
 | 
			
		||||
							<div class="bold df ac">
 | 
			
		||||
								{{if $file.IsBin}}
 | 
			
		||||
									{{$.i18n.Tr "repo.diff.bin"}}
 | 
			
		||||
								{{else if not $file.IsRenamed}}
 | 
			
		||||
								{{else}}
 | 
			
		||||
									{{template "repo/diff/stats" dict "file" . "root" $}}
 | 
			
		||||
								{{end}}
 | 
			
		||||
							</div>
 | 
			
		||||
@@ -105,7 +103,6 @@
 | 
			
		||||
						</div>
 | 
			
		||||
					</h4>
 | 
			
		||||
					<div class="diff-file-body ui attached unstackable table segment">
 | 
			
		||||
						{{if ne $file.Type 4}}
 | 
			
		||||
						<div class="file-body file-code has-context-menu{{if not $isImage}} code-diff{{end}}{{if $.IsSplitStyle}} code-diff-split{{else}} code-diff-unified{{end}}{{if $isImage}} py-4{{end}}">
 | 
			
		||||
							<table class="chroma{{if $isImage}} w-100{{end}}">
 | 
			
		||||
								<tbody>
 | 
			
		||||
@@ -121,14 +118,13 @@
 | 
			
		||||
								</tbody>
 | 
			
		||||
							</table>
 | 
			
		||||
						</div>
 | 
			
		||||
						{{end}}
 | 
			
		||||
					</div>
 | 
			
		||||
				</div>
 | 
			
		||||
			{{end}}
 | 
			
		||||
		{{end}}
 | 
			
		||||
 | 
			
		||||
		{{if .Diff.IsIncomplete}}
 | 
			
		||||
			<div class="diff-file-box diff-box file-content">
 | 
			
		||||
			<div class="diff-file-box diff-box file-content mt-3">
 | 
			
		||||
				<h4 class="ui top attached normal header">
 | 
			
		||||
					{{$.i18n.Tr "repo.diff.too_many_files"}}
 | 
			
		||||
				</h4>
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
{{ $createdStr:= TimeSinceUnix .CreatedUnix $.root.Lang }}
 | 
			
		||||
<div class="comment" id="{{.HashTag}}">
 | 
			
		||||
	{{if .OriginalAuthor }}
 | 
			
		||||
		<span class="avatar"><img src="/img/avatar_default.png"></span>
 | 
			
		||||
		<span class="avatar"><img src="{{AppSubUrl}}/img/avatar_default.png"></span>
 | 
			
		||||
	{{else}}
 | 
			
		||||
		<a class="avatar" {{if gt .Poster.ID 0}}href="{{.Poster.HomeLink}}"{{end}}>
 | 
			
		||||
			{{avatar .Poster}}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,17 +3,21 @@
 | 
			
		||||
{{$isNotPending := (not (eq (index .comments 0).Review.Type 0))}}
 | 
			
		||||
<div class="conversation-holder" data-path="{{(index .comments 0).TreePath}}" data-side="{{if lt (index .comments 0).Line 0}}left{{else}}right{{end}}" data-idx="{{(index .comments 0).UnsignedLine}}">
 | 
			
		||||
	{{if $resolved}}
 | 
			
		||||
		<div class="ui attached header resolved-placeholder">
 | 
			
		||||
			<span class="ui grey text left"><b>{{$resolveDoer.Name}}</b> {{$.i18n.Tr "repo.issues.review.resolved_by"}}</span>
 | 
			
		||||
			<button id="show-outdated-{{(index .comments 0).ID}}" data-comment="{{(index .comments 0).ID}}" class="ui tiny right labeled button show-outdated">
 | 
			
		||||
				{{svg "octicon-unfold"}}
 | 
			
		||||
		<div class="ui attached header resolved-placeholder df ac sb">
 | 
			
		||||
			<div class="ui grey text">
 | 
			
		||||
				<b>{{$resolveDoer.Name}}</b> {{$.i18n.Tr "repo.issues.review.resolved_by"}}
 | 
			
		||||
			</div>
 | 
			
		||||
			<div>
 | 
			
		||||
				<button id="show-outdated-{{(index .comments 0).ID}}" data-comment="{{(index .comments 0).ID}}" class="ui tiny right labeled button show-outdated df ac">
 | 
			
		||||
					{{svg "octicon-unfold" 16 "mr-3"}}
 | 
			
		||||
					{{$.i18n.Tr "repo.issues.review.show_resolved"}}
 | 
			
		||||
				</button>
 | 
			
		||||
			<button id="hide-outdated-{{(index .comments 0).ID}}" data-comment="{{(index .comments 0).ID}}" class="hide ui tiny right labeled button hide-outdated">
 | 
			
		||||
				{{svg "octicon-fold"}}
 | 
			
		||||
				<button id="hide-outdated-{{(index .comments 0).ID}}" data-comment="{{(index .comments 0).ID}}" class="hide ui tiny right labeled button hide-outdated df ac">
 | 
			
		||||
					{{svg "octicon-fold" 16 "mr-3"}}
 | 
			
		||||
					{{$.i18n.Tr "repo.issues.review.hide_resolved"}}
 | 
			
		||||
				</button>
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
	{{end}}
 | 
			
		||||
	<div id="code-comments-{{(index  .comments 0).ID}}" class="field comment-code-cloud {{if $resolved}}hide{{end}}">
 | 
			
		||||
		<div class="comment-list">
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
<div id="rev-container">
 | 
			
		||||
	<ul id="rev-list">
 | 
			
		||||
		{{ range $commitI, $commit := .Graph.Commits }}
 | 
			
		||||
			<li id="commit-{{$commit.Rev}}" data-flow="{{$commit.Flow}}">
 | 
			
		||||
			<li {{if $commit.Rev}}id="commit-{{$commit.Rev}}"{{end}} data-flow="{{$commit.Flow}}">
 | 
			
		||||
				{{ if $commit.OnlyRelation }}
 | 
			
		||||
					<span />
 | 
			
		||||
					<span></span>
 | 
			
		||||
				{{ else }}
 | 
			
		||||
					<span class="sha" id="{{$commit.ShortRev}}">
 | 
			
		||||
						{{$class := "ui sha label"}}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,8 @@
 | 
			
		||||
	<div class="ui container">
 | 
			
		||||
		<div class="ui three column stackable grid">
 | 
			
		||||
			<div class="column">
 | 
			
		||||
				<h3>{{.Milestone.Name}}</h3>
 | 
			
		||||
				<div class="content">
 | 
			
		||||
				<h1>{{.Milestone.Name}}</h1>
 | 
			
		||||
				<div class="markdown content">
 | 
			
		||||
					{{.Milestone.RenderedContent|Str2html}}
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,7 @@
 | 
			
		||||
		<div class="milestone list">
 | 
			
		||||
			{{range .Milestones}}
 | 
			
		||||
				<li class="item">
 | 
			
		||||
					{{svg "octicon-milestone"}} <a href="{{$.RepoLink}}/milestone/{{.ID}}">{{.Name}}</a>
 | 
			
		||||
					{{svg "octicon-milestone" 16 "mr-2"}} <a href="{{$.RepoLink}}/milestone/{{.ID}}">{{.Name}}</a>
 | 
			
		||||
					<div class="ui right green progress" data-percent="{{.Completeness}}">
 | 
			
		||||
						<div class="bar" {{if not .Completeness}}style="background-color: transparent"{{end}}>
 | 
			
		||||
							<div class="progress"></div>
 | 
			
		||||
@@ -80,7 +80,7 @@
 | 
			
		||||
						</div>
 | 
			
		||||
					{{end}}
 | 
			
		||||
					{{if .Content}}
 | 
			
		||||
						<div class="content">
 | 
			
		||||
						<div class="markdown content">
 | 
			
		||||
							{{.RenderedContent|Str2html}}
 | 
			
		||||
						</div>
 | 
			
		||||
					{{end}}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@
 | 
			
		||||
		<ui class="ui timeline">
 | 
			
		||||
			<div id="{{.Issue.HashTag}}" class="timeline-item comment first">
 | 
			
		||||
			{{if .Issue.OriginalAuthor }}
 | 
			
		||||
				<span class="timeline-avatar"><img src="/img/avatar_default.png"></span>
 | 
			
		||||
				<span class="timeline-avatar"><img src="{{AppSubUrl}}/img/avatar_default.png"></span>
 | 
			
		||||
			{{else}}
 | 
			
		||||
				<a class="timeline-avatar" {{if gt .Issue.Poster.ID 0}}href="{{.Issue.Poster.HomeLink}}"{{end}}>
 | 
			
		||||
					{{avatar .Issue.Poster}}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@
 | 
			
		||||
	{{if eq .Type 0}}
 | 
			
		||||
		<div class="timeline-item comment" id="{{.HashTag}}">
 | 
			
		||||
		{{if .OriginalAuthor }}
 | 
			
		||||
			<span class="timeline-avatar"><img src="/img/avatar_default.png"></span>
 | 
			
		||||
			<span class="timeline-avatar"><img src="{{AppSubUrl}}/img/avatar_default.png"></span>
 | 
			
		||||
		{{else}}
 | 
			
		||||
			<a class="timeline-avatar" {{if gt .Poster.ID 0}}href="{{.Poster.HomeLink}}"{{end}}>
 | 
			
		||||
				{{avatar .Poster}}
 | 
			
		||||
@@ -459,22 +459,31 @@
 | 
			
		||||
				{{ range $filename, $lines := .Review.CodeComments}}
 | 
			
		||||
					{{range $line, $comms := $lines}}
 | 
			
		||||
							<div class="ui segments">
 | 
			
		||||
								<div class="ui segment py-3">
 | 
			
		||||
								<div class="ui segment py-3 df ac sb">
 | 
			
		||||
									{{$invalid := (index $comms 0).Invalidated}}
 | 
			
		||||
									{{$resolved := (index $comms 0).IsResolved}}
 | 
			
		||||
									{{$resolveDoer := (index $comms 0).ResolveDoer}}
 | 
			
		||||
									{{$isNotPending := (not (eq (index $comms 0).Review.Type 0))}}
 | 
			
		||||
									<div class="df ac">
 | 
			
		||||
										<a href="{{(index $comms 0).CodeCommentURL}}" class="file-comment ml-3">{{$filename}}</a>
 | 
			
		||||
										{{if $invalid }}
 | 
			
		||||
											<span class="ui label basic small ml-3">
 | 
			
		||||
												{{$.i18n.Tr "repo.issues.review.outdated"}}
 | 
			
		||||
											</span>
 | 
			
		||||
										{{end}}
 | 
			
		||||
									</div>
 | 
			
		||||
									<div>
 | 
			
		||||
										{{if or $invalid $resolved}}
 | 
			
		||||
									<button id="show-outdated-{{(index $comms 0).ID}}" data-comment="{{(index $comms 0).ID}}" class="{{if not $resolved}}hide {{end}}ui compact right labeled button show-outdated">
 | 
			
		||||
										{{svg "octicon-unfold"}}
 | 
			
		||||
											<button id="show-outdated-{{(index $comms 0).ID}}" data-comment="{{(index $comms 0).ID}}" class="{{if not $resolved}}hide {{end}}ui compact right labeled button show-outdated df ac">
 | 
			
		||||
												{{svg "octicon-unfold" 16 "mr-3"}}
 | 
			
		||||
												{{if $resolved}}
 | 
			
		||||
													{{$.i18n.Tr "repo.issues.review.show_resolved"}}
 | 
			
		||||
												{{else}}
 | 
			
		||||
													{{$.i18n.Tr "repo.issues.review.show_outdated"}}
 | 
			
		||||
												{{end}}
 | 
			
		||||
											</button>
 | 
			
		||||
									<button id="hide-outdated-{{(index $comms 0).ID}}" data-comment="{{(index $comms 0).ID}}" class="{{if $resolved}}hide {{end}}ui compact right labeled button hide-outdated">
 | 
			
		||||
										{{svg "octicon-fold"}}
 | 
			
		||||
											<button id="hide-outdated-{{(index $comms 0).ID}}" data-comment="{{(index $comms 0).ID}}" class="{{if $resolved}}hide {{end}}ui compact right labeled button hide-outdated df ac">
 | 
			
		||||
												{{svg "octicon-fold" 16 "mr-3"}}
 | 
			
		||||
												{{if $resolved}}
 | 
			
		||||
													{{$.i18n.Tr "repo.issues.review.hide_resolved"}}
 | 
			
		||||
												{{else}}
 | 
			
		||||
@@ -482,12 +491,7 @@
 | 
			
		||||
												{{end}}
 | 
			
		||||
											</button>
 | 
			
		||||
										{{end}}
 | 
			
		||||
								<a href="{{(index $comms 0).CodeCommentURL}}" class="file-comment">{{$filename}}</a>
 | 
			
		||||
								{{if $invalid }}
 | 
			
		||||
									<span class="ui label basic small yellow">
 | 
			
		||||
										{{$.i18n.Tr "repo.issues.review.outdated"}}
 | 
			
		||||
									</span>
 | 
			
		||||
								{{end}}
 | 
			
		||||
									</div>
 | 
			
		||||
								</div>
 | 
			
		||||
								{{$diff := (CommentMustAsDiff (index $comms 0))}}
 | 
			
		||||
								{{if $diff}}
 | 
			
		||||
 
 | 
			
		||||
@@ -578,8 +578,6 @@
 | 
			
		||||
					{{end}}
 | 
			
		||||
				</button>
 | 
			
		||||
			</div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
			<div class="ui tiny modal" id="lock">
 | 
			
		||||
				<div class="header">
 | 
			
		||||
					{{ if .Issue.IsLocked }}
 | 
			
		||||
@@ -588,7 +586,6 @@
 | 
			
		||||
						{{.i18n.Tr "repo.issues.lock.title"}}
 | 
			
		||||
					{{end}}
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
				<div class="content">
 | 
			
		||||
					<div class="ui warning message text left">
 | 
			
		||||
						{{ if .Issue.IsLocked }}
 | 
			
		||||
 
 | 
			
		||||
@@ -71,8 +71,8 @@
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
				</div>
 | 
			
		||||
		{{end}}
 | 
			
		||||
			</div>
 | 
			
		||||
		{{end}}
 | 
			
		||||
 | 
			
		||||
	{{if .ContextUser.IsOrganization}}
 | 
			
		||||
		<div class="right stackable menu">
 | 
			
		||||
@@ -102,4 +102,5 @@
 | 
			
		||||
		</div>
 | 
			
		||||
	{{end}}
 | 
			
		||||
	</div>
 | 
			
		||||
</div>
 | 
			
		||||
<div class="ui divider"></div>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								vendor/code.gitea.io/sdk/gitea/admin_cron.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/code.gitea.io/sdk/gitea/admin_cron.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -39,6 +39,9 @@ func (c *Client) RunCronTasks(task string) (*Response, error) {
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := escapeValidatePathSegments(&task); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("POST", fmt.Sprintf("/admin/cron/%s", task), jsonHeader, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								vendor/code.gitea.io/sdk/gitea/admin_org.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/code.gitea.io/sdk/gitea/admin_org.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -26,6 +26,9 @@ func (c *Client) AdminListOrgs(opt AdminListOrgsOptions) ([]*Organization, *Resp
 | 
			
		||||
 | 
			
		||||
// AdminCreateOrg create an organization
 | 
			
		||||
func (c *Client) AdminCreateOrg(user string, opt CreateOrgOption) (*Organization, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(&opt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								vendor/code.gitea.io/sdk/gitea/admin_repo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/code.gitea.io/sdk/gitea/admin_repo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -12,6 +12,9 @@ import (
 | 
			
		||||
 | 
			
		||||
// AdminCreateRepo create a repo
 | 
			
		||||
func (c *Client) AdminCreateRepo(user string, opt CreateRepoOption) (*Repository, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(&opt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								vendor/code.gitea.io/sdk/gitea/admin_user.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								vendor/code.gitea.io/sdk/gitea/admin_user.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -65,12 +65,12 @@ func (c *Client) AdminCreateUser(opt CreateUserOption) (*User, *Response, error)
 | 
			
		||||
type EditUserOption struct {
 | 
			
		||||
	SourceID                int64   `json:"source_id"`
 | 
			
		||||
	LoginName               string  `json:"login_name"`
 | 
			
		||||
	FullName                string `json:"full_name"`
 | 
			
		||||
	Email                   string `json:"email"`
 | 
			
		||||
	Email                   *string `json:"email"`
 | 
			
		||||
	FullName                *string `json:"full_name"`
 | 
			
		||||
	Password                string  `json:"password"`
 | 
			
		||||
	MustChangePassword      *bool   `json:"must_change_password"`
 | 
			
		||||
	Website                 string `json:"website"`
 | 
			
		||||
	Location                string `json:"location"`
 | 
			
		||||
	Website                 *string `json:"website"`
 | 
			
		||||
	Location                *string `json:"location"`
 | 
			
		||||
	Active                  *bool   `json:"active"`
 | 
			
		||||
	Admin                   *bool   `json:"admin"`
 | 
			
		||||
	AllowGitHook            *bool   `json:"allow_git_hook"`
 | 
			
		||||
@@ -82,6 +82,9 @@ type EditUserOption struct {
 | 
			
		||||
 | 
			
		||||
// AdminEditUser modify user informations
 | 
			
		||||
func (c *Client) AdminEditUser(user string, opt EditUserOption) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(&opt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
@@ -92,12 +95,18 @@ func (c *Client) AdminEditUser(user string, opt EditUserOption) (*Response, erro
 | 
			
		||||
 | 
			
		||||
// AdminDeleteUser delete one user according name
 | 
			
		||||
func (c *Client) AdminDeleteUser(user string) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/admin/users/%s", user), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AdminCreateUserPublicKey adds a public key for the user
 | 
			
		||||
func (c *Client) AdminCreateUserPublicKey(user string, opt CreateKeyOption) (*PublicKey, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(&opt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
@@ -109,6 +118,9 @@ func (c *Client) AdminCreateUserPublicKey(user string, opt CreateKeyOption) (*Pu
 | 
			
		||||
 | 
			
		||||
// AdminDeleteUserPublicKey deletes a user's public key
 | 
			
		||||
func (c *Client) AdminDeleteUserPublicKey(user string, keyID int) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/admin/users/%s/keys/%d", user, keyID), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								vendor/code.gitea.io/sdk/gitea/attachment.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								vendor/code.gitea.io/sdk/gitea/attachment.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -31,6 +31,9 @@ type ListReleaseAttachmentsOptions struct {
 | 
			
		||||
 | 
			
		||||
// ListReleaseAttachments list release's attachments
 | 
			
		||||
func (c *Client) ListReleaseAttachments(user, repo string, release int64, opt ListReleaseAttachmentsOptions) ([]*Attachment, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	attachments := make([]*Attachment, 0, opt.PageSize)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET",
 | 
			
		||||
@@ -41,6 +44,9 @@ func (c *Client) ListReleaseAttachments(user, repo string, release int64, opt Li
 | 
			
		||||
 | 
			
		||||
// GetReleaseAttachment returns the requested attachment
 | 
			
		||||
func (c *Client) GetReleaseAttachment(user, repo string, release int64, id int64) (*Attachment, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	a := new(Attachment)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET",
 | 
			
		||||
		fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, id),
 | 
			
		||||
@@ -50,6 +56,9 @@ func (c *Client) GetReleaseAttachment(user, repo string, release int64, id int64
 | 
			
		||||
 | 
			
		||||
// CreateReleaseAttachment creates an attachment for the given release
 | 
			
		||||
func (c *Client) CreateReleaseAttachment(user, repo string, release int64, file io.Reader, filename string) (*Attachment, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	// Write file to body
 | 
			
		||||
	body := new(bytes.Buffer)
 | 
			
		||||
	writer := multipart.NewWriter(body)
 | 
			
		||||
@@ -80,6 +89,9 @@ type EditAttachmentOptions struct {
 | 
			
		||||
 | 
			
		||||
// EditReleaseAttachment updates the given attachment with the given options
 | 
			
		||||
func (c *Client) EditReleaseAttachment(user, repo string, release int64, attachment int64, form EditAttachmentOptions) (*Attachment, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(&form)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
@@ -91,6 +103,9 @@ func (c *Client) EditReleaseAttachment(user, repo string, release int64, attachm
 | 
			
		||||
 | 
			
		||||
// DeleteReleaseAttachment deletes the given attachment including the uploaded file
 | 
			
		||||
func (c *Client) DeleteReleaseAttachment(user, repo string, release int64, id int64) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, id), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										156
									
								
								vendor/code.gitea.io/sdk/gitea/client.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										156
									
								
								vendor/code.gitea.io/sdk/gitea/client.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -13,6 +13,7 @@ import (
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
@@ -23,10 +24,10 @@ var jsonHeader = http.Header{"content-type": []string{"application/json"}}
 | 
			
		||||
 | 
			
		||||
// Version return the library version
 | 
			
		||||
func Version() string {
 | 
			
		||||
	return "0.13.0"
 | 
			
		||||
	return "0.14.0"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Client represents a Gitea API client.
 | 
			
		||||
// Client represents a thread-safe Gitea API client.
 | 
			
		||||
type Client struct {
 | 
			
		||||
	url            string
 | 
			
		||||
	accessToken    string
 | 
			
		||||
@@ -37,8 +38,9 @@ type Client struct {
 | 
			
		||||
	debug          bool
 | 
			
		||||
	client         *http.Client
 | 
			
		||||
	ctx            context.Context
 | 
			
		||||
	mutex          sync.RWMutex
 | 
			
		||||
	serverVersion  *version.Version
 | 
			
		||||
	versionLock   sync.RWMutex
 | 
			
		||||
	getVersionOnce sync.Once
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Response represents the gitea response
 | 
			
		||||
@@ -47,6 +49,7 @@ type Response struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewClient initializes and returns a API client.
 | 
			
		||||
// Usage of all gitea.Client methods is concurrency-safe.
 | 
			
		||||
func NewClient(url string, options ...func(*Client)) (*Client, error) {
 | 
			
		||||
	client := &Client{
 | 
			
		||||
		url:    strings.TrimSuffix(url, "/"),
 | 
			
		||||
@@ -56,7 +59,7 @@ func NewClient(url string, options ...func(*Client)) (*Client, error) {
 | 
			
		||||
	for _, opt := range options {
 | 
			
		||||
		opt(client)
 | 
			
		||||
	}
 | 
			
		||||
	if err := client.checkServerVersionGreaterThanOrEqual(version1_10_0); err != nil {
 | 
			
		||||
	if err := client.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return client, nil
 | 
			
		||||
@@ -72,14 +75,23 @@ func NewClientWithHTTP(url string, httpClient *http.Client) *Client {
 | 
			
		||||
// SetHTTPClient is an option for NewClient to set custom http client
 | 
			
		||||
func SetHTTPClient(httpClient *http.Client) func(client *Client) {
 | 
			
		||||
	return func(client *Client) {
 | 
			
		||||
		client.client = httpClient
 | 
			
		||||
		client.SetHTTPClient(httpClient)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetHTTPClient replaces default http.Client with user given one.
 | 
			
		||||
func (c *Client) SetHTTPClient(client *http.Client) {
 | 
			
		||||
	c.mutex.Lock()
 | 
			
		||||
	c.client = client
 | 
			
		||||
	c.mutex.Unlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetToken is an option for NewClient to set token
 | 
			
		||||
func SetToken(token string) func(client *Client) {
 | 
			
		||||
	return func(client *Client) {
 | 
			
		||||
		client.mutex.Lock()
 | 
			
		||||
		client.accessToken = token
 | 
			
		||||
		client.mutex.Unlock()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -92,7 +104,9 @@ func SetBasicAuth(username, password string) func(client *Client) {
 | 
			
		||||
 | 
			
		||||
// SetBasicAuth sets username and password
 | 
			
		||||
func (c *Client) SetBasicAuth(username, password string) {
 | 
			
		||||
	c.mutex.Lock()
 | 
			
		||||
	c.username, c.password = username, password
 | 
			
		||||
	c.mutex.Unlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetOTP is an option for NewClient to set OTP for 2FA
 | 
			
		||||
@@ -104,7 +118,9 @@ func SetOTP(otp string) func(client *Client) {
 | 
			
		||||
 | 
			
		||||
// SetOTP sets OTP for 2FA
 | 
			
		||||
func (c *Client) SetOTP(otp string) {
 | 
			
		||||
	c.mutex.Lock()
 | 
			
		||||
	c.otp = otp
 | 
			
		||||
	c.mutex.Unlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetContext is an option for NewClient to set context
 | 
			
		||||
@@ -116,12 +132,9 @@ func SetContext(ctx context.Context) func(client *Client) {
 | 
			
		||||
 | 
			
		||||
// SetContext set context witch is used for http requests
 | 
			
		||||
func (c *Client) SetContext(ctx context.Context) {
 | 
			
		||||
	c.mutex.Lock()
 | 
			
		||||
	c.ctx = ctx
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetHTTPClient replaces default http.Client with user given one.
 | 
			
		||||
func (c *Client) SetHTTPClient(client *http.Client) {
 | 
			
		||||
	c.client = client
 | 
			
		||||
	c.mutex.Unlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetSudo is an option for NewClient to set sudo header
 | 
			
		||||
@@ -133,43 +146,57 @@ func SetSudo(sudo string) func(client *Client) {
 | 
			
		||||
 | 
			
		||||
// SetSudo sets username to impersonate.
 | 
			
		||||
func (c *Client) SetSudo(sudo string) {
 | 
			
		||||
	c.mutex.Lock()
 | 
			
		||||
	c.sudo = sudo
 | 
			
		||||
	c.mutex.Unlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetDebugMode is an option for NewClient to enable debug mode
 | 
			
		||||
func SetDebugMode() func(client *Client) {
 | 
			
		||||
	return func(client *Client) {
 | 
			
		||||
		client.mutex.Lock()
 | 
			
		||||
		client.debug = true
 | 
			
		||||
		client.mutex.Unlock()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) getWebResponse(method, path string, body io.Reader) ([]byte, *Response, error) {
 | 
			
		||||
	if c.debug {
 | 
			
		||||
	c.mutex.RLock()
 | 
			
		||||
	debug := c.debug
 | 
			
		||||
	if debug {
 | 
			
		||||
		fmt.Printf("%s: %s\nBody: %v\n", method, c.url+path, body)
 | 
			
		||||
	}
 | 
			
		||||
	req, err := http.NewRequestWithContext(c.ctx, method, c.url+path, body)
 | 
			
		||||
 | 
			
		||||
	client := c.client // client ref can change from this point on so safe it
 | 
			
		||||
	c.mutex.RUnlock()
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	resp, err := c.client.Do(req)
 | 
			
		||||
 | 
			
		||||
	resp, err := client.Do(req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
	data, err := ioutil.ReadAll(resp.Body)
 | 
			
		||||
	if c.debug {
 | 
			
		||||
	if debug {
 | 
			
		||||
		fmt.Printf("Response: %v\n\n", resp)
 | 
			
		||||
	}
 | 
			
		||||
	return data, &Response{resp}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) doRequest(method, path string, header http.Header, body io.Reader) (*Response, error) {
 | 
			
		||||
	if c.debug {
 | 
			
		||||
	c.mutex.RLock()
 | 
			
		||||
	debug := c.debug
 | 
			
		||||
	if debug {
 | 
			
		||||
		fmt.Printf("%s: %s\nHeader: %v\nBody: %s\n", method, c.url+"/api/v1"+path, header, body)
 | 
			
		||||
	}
 | 
			
		||||
	req, err := http.NewRequestWithContext(c.ctx, method, c.url+"/api/v1"+path, body)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		c.mutex.RUnlock()
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if len(c.accessToken) != 0 {
 | 
			
		||||
@@ -184,20 +211,66 @@ func (c *Client) doRequest(method, path string, header http.Header, body io.Read
 | 
			
		||||
	if len(c.sudo) != 0 {
 | 
			
		||||
		req.Header.Set("Sudo", c.sudo)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	client := c.client // client ref can change from this point on so safe it
 | 
			
		||||
	c.mutex.RUnlock()
 | 
			
		||||
 | 
			
		||||
	for k, v := range header {
 | 
			
		||||
		req.Header[k] = v
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resp, err := c.client.Do(req)
 | 
			
		||||
	resp, err := client.Do(req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if c.debug {
 | 
			
		||||
	if debug {
 | 
			
		||||
		fmt.Printf("Response: %v\n\n", resp)
 | 
			
		||||
	}
 | 
			
		||||
	return &Response{resp}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Converts a response for a HTTP status code indicating an error condition
 | 
			
		||||
// (non-2XX) to a well-known error value and response body. For non-problematic
 | 
			
		||||
// (2XX) status codes nil will be returned. Note that on a non-2XX response, the
 | 
			
		||||
// response body stream will have been read and, hence, is closed on return.
 | 
			
		||||
func statusCodeToErr(resp *Response) (body []byte, err error) {
 | 
			
		||||
	// no error
 | 
			
		||||
	if resp.StatusCode/100 == 2 {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//
 | 
			
		||||
	// error: body will be read for details
 | 
			
		||||
	//
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
	data, err := ioutil.ReadAll(resp.Body)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("body read on HTTP error %d: %v", resp.StatusCode, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch resp.StatusCode {
 | 
			
		||||
	case 403:
 | 
			
		||||
		return data, errors.New("403 Forbidden")
 | 
			
		||||
	case 404:
 | 
			
		||||
		return data, errors.New("404 Not Found")
 | 
			
		||||
	case 409:
 | 
			
		||||
		return data, errors.New("409 Conflict")
 | 
			
		||||
	case 422:
 | 
			
		||||
		return data, fmt.Errorf("422 Unprocessable Entity: %s", string(data))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	path := resp.Request.URL.Path
 | 
			
		||||
	method := resp.Request.Method
 | 
			
		||||
	header := resp.Request.Header
 | 
			
		||||
	errMap := make(map[string]interface{})
 | 
			
		||||
	if err = json.Unmarshal(data, &errMap); err != nil {
 | 
			
		||||
		// when the JSON can't be parsed, data was probably empty or a
 | 
			
		||||
		// plain string, so we try to return a helpful error anyway
 | 
			
		||||
		return data, fmt.Errorf("Unknown API Error: %d\nRequest: '%s' with '%s' method '%s' header and '%s' body", resp.StatusCode, path, method, header, string(data))
 | 
			
		||||
	}
 | 
			
		||||
	return data, errors.New(errMap["message"].(string))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) getResponse(method, path string, header http.Header, body io.Reader) ([]byte, *Response, error) {
 | 
			
		||||
	resp, err := c.doRequest(method, path, header, body)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -205,32 +278,18 @@ func (c *Client) getResponse(method, path string, header http.Header, body io.Re
 | 
			
		||||
	}
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
 | 
			
		||||
	data, err := ioutil.ReadAll(resp.Body)
 | 
			
		||||
	// check for errors
 | 
			
		||||
	data, err := statusCodeToErr(resp)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return data, resp, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// success (2XX), read body
 | 
			
		||||
	data, err = ioutil.ReadAll(resp.Body)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, resp, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch resp.StatusCode {
 | 
			
		||||
	case 403:
 | 
			
		||||
		return data, resp, errors.New("403 Forbidden")
 | 
			
		||||
	case 404:
 | 
			
		||||
		return data, resp, errors.New("404 Not Found")
 | 
			
		||||
	case 409:
 | 
			
		||||
		return data, resp, errors.New("409 Conflict")
 | 
			
		||||
	case 422:
 | 
			
		||||
		return data, resp, fmt.Errorf("422 Unprocessable Entity: %s", string(data))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if resp.StatusCode/100 != 2 {
 | 
			
		||||
		errMap := make(map[string]interface{})
 | 
			
		||||
		if err = json.Unmarshal(data, &errMap); err != nil {
 | 
			
		||||
			// when the JSON can't be parsed, data was probably empty or a plain string,
 | 
			
		||||
			// so we try to return a helpful error anyway
 | 
			
		||||
			return data, resp, fmt.Errorf("Unknown API Error: %d\nRequest: '%s' with '%s' method '%s' header and '%s' body", resp.StatusCode, path, method, header, string(data))
 | 
			
		||||
		}
 | 
			
		||||
		return data, resp, errors.New(errMap["message"].(string))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return data, resp, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -251,3 +310,24 @@ func (c *Client) getStatusCode(method, path string, header http.Header, body io.
 | 
			
		||||
 | 
			
		||||
	return resp.StatusCode, resp, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// pathEscapeSegments escapes segments of a path while not escaping forward slash
 | 
			
		||||
func pathEscapeSegments(path string) string {
 | 
			
		||||
	slice := strings.Split(path, "/")
 | 
			
		||||
	for index := range slice {
 | 
			
		||||
		slice[index] = url.PathEscape(slice[index])
 | 
			
		||||
	}
 | 
			
		||||
	escapedPath := strings.Join(slice, "/")
 | 
			
		||||
	return escapedPath
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// escapeValidatePathSegments is a help function to validate and encode url path segments
 | 
			
		||||
func escapeValidatePathSegments(seg ...*string) error {
 | 
			
		||||
	for i := range seg {
 | 
			
		||||
		if seg[i] == nil || len(*seg[i]) == 0 {
 | 
			
		||||
			return fmt.Errorf("path segment [%d] is empty", i)
 | 
			
		||||
		}
 | 
			
		||||
		*seg[i] = url.PathEscape(*seg[i])
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								vendor/code.gitea.io/sdk/gitea/fork.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/code.gitea.io/sdk/gitea/fork.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -17,6 +17,9 @@ type ListForksOptions struct {
 | 
			
		||||
 | 
			
		||||
// ListForks list a repository's forks
 | 
			
		||||
func (c *Client) ListForks(user string, repo string, opt ListForksOptions) ([]*Repository, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	forks := make([]*Repository, opt.PageSize)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET",
 | 
			
		||||
@@ -33,6 +36,9 @@ type CreateForkOption struct {
 | 
			
		||||
 | 
			
		||||
// CreateFork create a fork of a repository
 | 
			
		||||
func (c *Client) CreateFork(user, repo string, form CreateForkOption) (*Repository, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(form)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								vendor/code.gitea.io/sdk/gitea/git_blob.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/code.gitea.io/sdk/gitea/git_blob.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -19,6 +19,9 @@ type GitBlobResponse struct {
 | 
			
		||||
 | 
			
		||||
// GetBlob get the blob of a repository file
 | 
			
		||||
func (c *Client) GetBlob(user, repo, sha string) (*GitBlobResponse, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo, &sha); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	blob := new(GitBlobResponse)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/blobs/%s", user, repo, sha), nil, nil, blob)
 | 
			
		||||
	return blob, resp, err
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								vendor/code.gitea.io/sdk/gitea/git_hook.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								vendor/code.gitea.io/sdk/gitea/git_hook.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -24,6 +24,9 @@ type ListRepoGitHooksOptions struct {
 | 
			
		||||
 | 
			
		||||
// ListRepoGitHooks list all the Git hooks of one repository
 | 
			
		||||
func (c *Client) ListRepoGitHooks(user, repo string, opt ListRepoGitHooksOptions) ([]*GitHook, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	hooks := make([]*GitHook, 0, opt.PageSize)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/git?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &hooks)
 | 
			
		||||
@@ -32,6 +35,9 @@ func (c *Client) ListRepoGitHooks(user, repo string, opt ListRepoGitHooksOptions
 | 
			
		||||
 | 
			
		||||
// GetRepoGitHook get a Git hook of a repository
 | 
			
		||||
func (c *Client) GetRepoGitHook(user, repo, id string) (*GitHook, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo, &id); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	h := new(GitHook)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), nil, nil, h)
 | 
			
		||||
	return h, resp, err
 | 
			
		||||
@@ -44,6 +50,9 @@ type EditGitHookOption struct {
 | 
			
		||||
 | 
			
		||||
// EditRepoGitHook modify one Git hook of a repository
 | 
			
		||||
func (c *Client) EditRepoGitHook(user, repo, id string, opt EditGitHookOption) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo, &id); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(&opt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
@@ -54,6 +63,9 @@ func (c *Client) EditRepoGitHook(user, repo, id string, opt EditGitHookOption) (
 | 
			
		||||
 | 
			
		||||
// DeleteRepoGitHook delete one Git hook from a repository
 | 
			
		||||
func (c *Client) DeleteRepoGitHook(user, repo, id string) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo, &id); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/code.gitea.io/sdk/gitea/go.mod
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/code.gitea.io/sdk/gitea/go.mod
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
module code.gitea.io/sdk/gitea
 | 
			
		||||
 | 
			
		||||
go 1.12
 | 
			
		||||
go 1.13
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/hashicorp/go-version v1.2.1
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/code.gitea.io/sdk/gitea/go.sum
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/code.gitea.io/sdk/gitea/go.sum
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -2,6 +2,8 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
 | 
			
		||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
 | 
			
		||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
 | 
			
		||||
github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI=
 | 
			
		||||
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
 | 
			
		||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 | 
			
		||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 | 
			
		||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								vendor/code.gitea.io/sdk/gitea/helper.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/code.gitea.io/sdk/gitea/helper.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
// Copyright 2020 The Gitea Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package gitea
 | 
			
		||||
 | 
			
		||||
// OptionalBool convert a bool to a bool reference
 | 
			
		||||
func OptionalBool(v bool) *bool {
 | 
			
		||||
	return &v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OptionalString convert a string to a string reference
 | 
			
		||||
func OptionalString(v string) *string {
 | 
			
		||||
	return &v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OptionalInt64 convert a int64 to a int64 reference
 | 
			
		||||
func OptionalInt64(v int64) *int64 {
 | 
			
		||||
	return &v
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								vendor/code.gitea.io/sdk/gitea/hook.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								vendor/code.gitea.io/sdk/gitea/hook.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -31,6 +31,9 @@ type ListHooksOptions struct {
 | 
			
		||||
 | 
			
		||||
// ListOrgHooks list all the hooks of one organization
 | 
			
		||||
func (c *Client) ListOrgHooks(org string, opt ListHooksOptions) ([]*Hook, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&org); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	hooks := make([]*Hook, 0, opt.PageSize)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/hooks?%s", org, opt.getURLQuery().Encode()), nil, nil, &hooks)
 | 
			
		||||
@@ -39,6 +42,9 @@ func (c *Client) ListOrgHooks(org string, opt ListHooksOptions) ([]*Hook, *Respo
 | 
			
		||||
 | 
			
		||||
// ListRepoHooks list all the hooks of one repository
 | 
			
		||||
func (c *Client) ListRepoHooks(user, repo string, opt ListHooksOptions) ([]*Hook, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	hooks := make([]*Hook, 0, opt.PageSize)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &hooks)
 | 
			
		||||
@@ -47,6 +53,9 @@ func (c *Client) ListRepoHooks(user, repo string, opt ListHooksOptions) ([]*Hook
 | 
			
		||||
 | 
			
		||||
// GetOrgHook get a hook of an organization
 | 
			
		||||
func (c *Client) GetOrgHook(org string, id int64) (*Hook, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&org); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	h := new(Hook)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), nil, nil, h)
 | 
			
		||||
	return h, resp, err
 | 
			
		||||
@@ -54,6 +63,9 @@ func (c *Client) GetOrgHook(org string, id int64) (*Hook, *Response, error) {
 | 
			
		||||
 | 
			
		||||
// GetRepoHook get a hook of a repository
 | 
			
		||||
func (c *Client) GetRepoHook(user, repo string, id int64) (*Hook, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	h := new(Hook)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), nil, nil, h)
 | 
			
		||||
	return h, resp, err
 | 
			
		||||
@@ -78,6 +90,9 @@ func (opt CreateHookOption) Validate() error {
 | 
			
		||||
 | 
			
		||||
// CreateOrgHook create one hook for an organization, with options
 | 
			
		||||
func (c *Client) CreateOrgHook(org string, opt CreateHookOption) (*Hook, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&org); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := opt.Validate(); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -92,6 +107,9 @@ func (c *Client) CreateOrgHook(org string, opt CreateHookOption) (*Hook, *Respon
 | 
			
		||||
 | 
			
		||||
// CreateRepoHook create one hook for a repository, with options
 | 
			
		||||
func (c *Client) CreateRepoHook(user, repo string, opt CreateHookOption) (*Hook, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(&opt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
@@ -111,6 +129,9 @@ type EditHookOption struct {
 | 
			
		||||
 | 
			
		||||
// EditOrgHook modify one hook of an organization, with hook id and options
 | 
			
		||||
func (c *Client) EditOrgHook(org string, id int64, opt EditHookOption) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&org); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(&opt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
@@ -121,6 +142,9 @@ func (c *Client) EditOrgHook(org string, id int64, opt EditHookOption) (*Respons
 | 
			
		||||
 | 
			
		||||
// EditRepoHook modify one hook of a repository, with hook id and options
 | 
			
		||||
func (c *Client) EditRepoHook(user, repo string, id int64, opt EditHookOption) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(&opt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
@@ -131,12 +155,18 @@ func (c *Client) EditRepoHook(user, repo string, id int64, opt EditHookOption) (
 | 
			
		||||
 | 
			
		||||
// DeleteOrgHook delete one hook from an organization, with hook id
 | 
			
		||||
func (c *Client) DeleteOrgHook(org string, id int64) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&org); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteRepoHook delete one hook from a repository, with hook id
 | 
			
		||||
func (c *Client) DeleteRepoHook(user, repo string, id int64) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										41
									
								
								vendor/code.gitea.io/sdk/gitea/issue.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										41
									
								
								vendor/code.gitea.io/sdk/gitea/issue.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -32,14 +32,18 @@ type RepositoryMeta struct {
 | 
			
		||||
type Issue struct {
 | 
			
		||||
	ID               int64      `json:"id"`
 | 
			
		||||
	URL              string     `json:"url"`
 | 
			
		||||
	HTMLURL          string     `json:"html_url"`
 | 
			
		||||
	Index            int64      `json:"number"`
 | 
			
		||||
	Poster           *User      `json:"user"`
 | 
			
		||||
	OriginalAuthor   string     `json:"original_author"`
 | 
			
		||||
	OriginalAuthorID int64      `json:"original_author_id"`
 | 
			
		||||
	Title            string     `json:"title"`
 | 
			
		||||
	Body             string     `json:"body"`
 | 
			
		||||
	Ref              string     `json:"ref"`
 | 
			
		||||
	Labels           []*Label   `json:"labels"`
 | 
			
		||||
	Milestone        *Milestone `json:"milestone"`
 | 
			
		||||
	// deprecated
 | 
			
		||||
	// TODO: rm on sdk 0.15.0
 | 
			
		||||
	Assignee  *User   `json:"assignee"`
 | 
			
		||||
	Assignees []*User `json:"assignees"`
 | 
			
		||||
	// Whether the issue is open or closed
 | 
			
		||||
@@ -128,11 +132,17 @@ func (c *Client) ListIssues(opt ListIssueOption) ([]*Issue, *Response, error) {
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for i := range issues {
 | 
			
		||||
		c.issueBackwardsCompatibility(issues[i])
 | 
			
		||||
	}
 | 
			
		||||
	return issues, resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListRepoIssues returns all issues for a given repository
 | 
			
		||||
func (c *Client) ListRepoIssues(owner, repo string, opt ListIssueOption) ([]*Issue, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	issues := make([]*Issue, 0, opt.PageSize)
 | 
			
		||||
 | 
			
		||||
@@ -146,16 +156,23 @@ func (c *Client) ListRepoIssues(owner, repo string, opt ListIssueOption) ([]*Iss
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for i := range issues {
 | 
			
		||||
		c.issueBackwardsCompatibility(issues[i])
 | 
			
		||||
	}
 | 
			
		||||
	return issues, resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetIssue returns a single issue for a given repository
 | 
			
		||||
func (c *Client) GetIssue(owner, repo string, index int64) (*Issue, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	issue := new(Issue)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index), nil, nil, issue)
 | 
			
		||||
	if e := c.checkServerVersionGreaterThanOrEqual(version1_12_0); e != nil && issue.Repository != nil {
 | 
			
		||||
		issue.Repository.Owner = strings.Split(issue.Repository.FullName, "/")[0]
 | 
			
		||||
	}
 | 
			
		||||
	c.issueBackwardsCompatibility(issue)
 | 
			
		||||
	return issue, resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -163,7 +180,9 @@ func (c *Client) GetIssue(owner, repo string, index int64) (*Issue, *Response, e
 | 
			
		||||
type CreateIssueOption struct {
 | 
			
		||||
	Title string `json:"title"`
 | 
			
		||||
	Body  string `json:"body"`
 | 
			
		||||
	// username of assignee
 | 
			
		||||
	Ref   string `json:"ref"`
 | 
			
		||||
	// deprecated
 | 
			
		||||
	// TODO: rm on sdk 0.15.0
 | 
			
		||||
	Assignee  string     `json:"assignee"`
 | 
			
		||||
	Assignees []string   `json:"assignees"`
 | 
			
		||||
	Deadline  *time.Time `json:"due_date"`
 | 
			
		||||
@@ -184,6 +203,9 @@ func (opt CreateIssueOption) Validate() error {
 | 
			
		||||
 | 
			
		||||
// CreateIssue create a new issue for a given repository
 | 
			
		||||
func (c *Client) CreateIssue(owner, repo string, opt CreateIssueOption) (*Issue, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := opt.Validate(); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -194,6 +216,7 @@ func (c *Client) CreateIssue(owner, repo string, opt CreateIssueOption) (*Issue,
 | 
			
		||||
	issue := new(Issue)
 | 
			
		||||
	resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues", owner, repo),
 | 
			
		||||
		jsonHeader, bytes.NewReader(body), issue)
 | 
			
		||||
	c.issueBackwardsCompatibility(issue)
 | 
			
		||||
	return issue, resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -201,11 +224,15 @@ func (c *Client) CreateIssue(owner, repo string, opt CreateIssueOption) (*Issue,
 | 
			
		||||
type EditIssueOption struct {
 | 
			
		||||
	Title string  `json:"title"`
 | 
			
		||||
	Body  *string `json:"body"`
 | 
			
		||||
	Ref   *string `json:"ref"`
 | 
			
		||||
	// deprecated
 | 
			
		||||
	// TODO: rm on sdk 0.15.0
 | 
			
		||||
	Assignee       *string    `json:"assignee"`
 | 
			
		||||
	Assignees      []string   `json:"assignees"`
 | 
			
		||||
	Milestone      *int64     `json:"milestone"`
 | 
			
		||||
	State          *StateType `json:"state"`
 | 
			
		||||
	Deadline       *time.Time `json:"due_date"`
 | 
			
		||||
	RemoveDeadline *bool      `json:"unset_due_date"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate the EditIssueOption struct
 | 
			
		||||
@@ -218,6 +245,9 @@ func (opt EditIssueOption) Validate() error {
 | 
			
		||||
 | 
			
		||||
// EditIssue modify an existing issue for a given repository
 | 
			
		||||
func (c *Client) EditIssue(owner, repo string, index int64, opt EditIssueOption) (*Issue, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := opt.Validate(); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -229,5 +259,14 @@ func (c *Client) EditIssue(owner, repo string, index int64, opt EditIssueOption)
 | 
			
		||||
	resp, err := c.getParsedResponse("PATCH",
 | 
			
		||||
		fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index),
 | 
			
		||||
		jsonHeader, bytes.NewReader(body), issue)
 | 
			
		||||
	c.issueBackwardsCompatibility(issue)
 | 
			
		||||
	return issue, resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) issueBackwardsCompatibility(issue *Issue) {
 | 
			
		||||
	if c.checkServerVersionGreaterThanOrEqual(version1_12_0) != nil {
 | 
			
		||||
		c.mutex.RLock()
 | 
			
		||||
		issue.HTMLURL = fmt.Sprintf("%s/%s/issues/%d", c.url, issue.Repository.FullName, issue.Index)
 | 
			
		||||
		c.mutex.RUnlock()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								vendor/code.gitea.io/sdk/gitea/issue_comment.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								vendor/code.gitea.io/sdk/gitea/issue_comment.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -47,6 +47,9 @@ func (opt *ListIssueCommentOptions) QueryEncode() string {
 | 
			
		||||
 | 
			
		||||
// ListIssueComments list comments on an issue.
 | 
			
		||||
func (c *Client) ListIssueComments(owner, repo string, index int64, opt ListIssueCommentOptions) ([]*Comment, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/%d/comments", owner, repo, index))
 | 
			
		||||
	link.RawQuery = opt.QueryEncode()
 | 
			
		||||
@@ -57,6 +60,9 @@ func (c *Client) ListIssueComments(owner, repo string, index int64, opt ListIssu
 | 
			
		||||
 | 
			
		||||
// ListRepoIssueComments list comments for a given repo.
 | 
			
		||||
func (c *Client) ListRepoIssueComments(owner, repo string, opt ListIssueCommentOptions) ([]*Comment, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/comments", owner, repo))
 | 
			
		||||
	link.RawQuery = opt.QueryEncode()
 | 
			
		||||
@@ -67,6 +73,9 @@ func (c *Client) ListRepoIssueComments(owner, repo string, opt ListIssueCommentO
 | 
			
		||||
 | 
			
		||||
// GetIssueComment get a comment for a given repo by id.
 | 
			
		||||
func (c *Client) GetIssueComment(owner, repo string, id int64) (*Comment, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	comment := new(Comment)
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
 | 
			
		||||
		return comment, nil, err
 | 
			
		||||
@@ -90,6 +99,9 @@ func (opt CreateIssueCommentOption) Validate() error {
 | 
			
		||||
 | 
			
		||||
// CreateIssueComment create comment on an issue.
 | 
			
		||||
func (c *Client) CreateIssueComment(owner, repo string, index int64, opt CreateIssueCommentOption) (*Comment, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := opt.Validate(); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -117,6 +129,9 @@ func (opt EditIssueCommentOption) Validate() error {
 | 
			
		||||
 | 
			
		||||
// EditIssueComment edits an issue comment.
 | 
			
		||||
func (c *Client) EditIssueComment(owner, repo string, commentID int64, opt EditIssueCommentOption) (*Comment, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := opt.Validate(); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -131,6 +146,9 @@ func (c *Client) EditIssueComment(owner, repo string, commentID int64, opt EditI
 | 
			
		||||
 | 
			
		||||
// DeleteIssueComment deletes an issue comment.
 | 
			
		||||
func (c *Client) DeleteIssueComment(owner, repo string, commentID int64) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, commentID), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										30
									
								
								vendor/code.gitea.io/sdk/gitea/issue_label.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								vendor/code.gitea.io/sdk/gitea/issue_label.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -29,6 +29,9 @@ type ListLabelsOptions struct {
 | 
			
		||||
 | 
			
		||||
// ListRepoLabels list labels of one repository
 | 
			
		||||
func (c *Client) ListRepoLabels(owner, repo string, opt ListLabelsOptions) ([]*Label, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	labels := make([]*Label, 0, opt.PageSize)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels?%s", owner, repo, opt.getURLQuery().Encode()), nil, nil, &labels)
 | 
			
		||||
@@ -37,6 +40,9 @@ func (c *Client) ListRepoLabels(owner, repo string, opt ListLabelsOptions) ([]*L
 | 
			
		||||
 | 
			
		||||
// GetRepoLabel get one label of repository by repo it
 | 
			
		||||
func (c *Client) GetRepoLabel(owner, repo string, id int64) (*Label, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	label := new(Label)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil, label)
 | 
			
		||||
	return label, resp, err
 | 
			
		||||
@@ -67,6 +73,9 @@ func (opt CreateLabelOption) Validate() error {
 | 
			
		||||
 | 
			
		||||
// CreateLabel create one label of repository
 | 
			
		||||
func (c *Client) CreateLabel(owner, repo string, opt CreateLabelOption) (*Label, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := opt.Validate(); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -114,6 +123,9 @@ func (opt EditLabelOption) Validate() error {
 | 
			
		||||
 | 
			
		||||
// EditLabel modify one label with options
 | 
			
		||||
func (c *Client) EditLabel(owner, repo string, id int64, opt EditLabelOption) (*Label, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := opt.Validate(); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -128,12 +140,18 @@ func (c *Client) EditLabel(owner, repo string, id int64, opt EditLabelOption) (*
 | 
			
		||||
 | 
			
		||||
// DeleteLabel delete one label of repository by id
 | 
			
		||||
func (c *Client) DeleteLabel(owner, repo string, id int64) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetIssueLabels get labels of one issue via issue id
 | 
			
		||||
func (c *Client) GetIssueLabels(owner, repo string, index int64, opts ListLabelsOptions) ([]*Label, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	labels := make([]*Label, 0, 5)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/labels?%s", owner, repo, index, opts.getURLQuery().Encode()), nil, nil, &labels)
 | 
			
		||||
	return labels, resp, err
 | 
			
		||||
@@ -147,6 +165,9 @@ type IssueLabelsOption struct {
 | 
			
		||||
 | 
			
		||||
// AddIssueLabels add one or more labels to one issue
 | 
			
		||||
func (c *Client) AddIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(&opt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
@@ -158,6 +179,9 @@ func (c *Client) AddIssueLabels(owner, repo string, index int64, opt IssueLabels
 | 
			
		||||
 | 
			
		||||
// ReplaceIssueLabels replace old labels of issue with new labels
 | 
			
		||||
func (c *Client) ReplaceIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(&opt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
@@ -170,12 +194,18 @@ func (c *Client) ReplaceIssueLabels(owner, repo string, index int64, opt IssueLa
 | 
			
		||||
// DeleteIssueLabel delete one label of one issue by issue id and label id
 | 
			
		||||
// TODO: maybe we need delete by label name and issue id
 | 
			
		||||
func (c *Client) DeleteIssueLabel(owner, repo string, index, label int64) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels/%d", owner, repo, index, label), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ClearIssueLabels delete all the labels of one issue.
 | 
			
		||||
func (c *Client) ClearIssueLabels(owner, repo string, index int64) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										24
									
								
								vendor/code.gitea.io/sdk/gitea/issue_milestone.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								vendor/code.gitea.io/sdk/gitea/issue_milestone.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -49,6 +49,9 @@ func (opt *ListMilestoneOption) QueryEncode() string {
 | 
			
		||||
 | 
			
		||||
// ListRepoMilestones list all the milestones of one repository
 | 
			
		||||
func (c *Client) ListRepoMilestones(owner, repo string, opt ListMilestoneOption) ([]*Milestone, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	milestones := make([]*Milestone, 0, opt.PageSize)
 | 
			
		||||
 | 
			
		||||
@@ -60,6 +63,9 @@ func (c *Client) ListRepoMilestones(owner, repo string, opt ListMilestoneOption)
 | 
			
		||||
 | 
			
		||||
// GetMilestone get one milestone by repo name and milestone id
 | 
			
		||||
func (c *Client) GetMilestone(owner, repo string, id int64) (*Milestone, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	milestone := new(Milestone)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil, milestone)
 | 
			
		||||
	return milestone, resp, err
 | 
			
		||||
@@ -72,6 +78,9 @@ func (c *Client) GetMilestoneByName(owner, repo string, name string) (*Milestone
 | 
			
		||||
		m, resp, err := c.resolveMilestoneByName(owner, repo, name)
 | 
			
		||||
		return m, resp, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	milestone := new(Milestone)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones/%s", owner, repo, name), nil, nil, milestone)
 | 
			
		||||
	return milestone, resp, err
 | 
			
		||||
@@ -95,6 +104,9 @@ func (opt CreateMilestoneOption) Validate() error {
 | 
			
		||||
 | 
			
		||||
// CreateMilestone create one milestone with options
 | 
			
		||||
func (c *Client) CreateMilestone(owner, repo string, opt CreateMilestoneOption) (*Milestone, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := opt.Validate(); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -135,6 +147,9 @@ func (opt EditMilestoneOption) Validate() error {
 | 
			
		||||
 | 
			
		||||
// EditMilestone modify milestone with options
 | 
			
		||||
func (c *Client) EditMilestone(owner, repo string, id int64, opt EditMilestoneOption) (*Milestone, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := opt.Validate(); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -157,6 +172,9 @@ func (c *Client) EditMilestoneByName(owner, repo string, name string, opt EditMi
 | 
			
		||||
		}
 | 
			
		||||
		return c.EditMilestone(owner, repo, m.ID, opt)
 | 
			
		||||
	}
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := opt.Validate(); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -171,6 +189,9 @@ func (c *Client) EditMilestoneByName(owner, repo string, name string, opt EditMi
 | 
			
		||||
 | 
			
		||||
// DeleteMilestone delete one milestone by id
 | 
			
		||||
func (c *Client) DeleteMilestone(owner, repo string, id int64) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
@@ -185,6 +206,9 @@ func (c *Client) DeleteMilestoneByName(owner, repo string, name string) (*Respon
 | 
			
		||||
		}
 | 
			
		||||
		return c.DeleteMilestone(owner, repo, m.ID)
 | 
			
		||||
	}
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/milestones/%s", owner, repo, name), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								vendor/code.gitea.io/sdk/gitea/issue_reaction.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								vendor/code.gitea.io/sdk/gitea/issue_reaction.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -20,7 +20,7 @@ type Reaction struct {
 | 
			
		||||
 | 
			
		||||
// GetIssueReactions get a list reactions of an issue
 | 
			
		||||
func (c *Client) GetIssueReactions(owner, repo string, index int64) ([]*Reaction, *Response, error) {
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	reactions := make([]*Reaction, 0, 10)
 | 
			
		||||
@@ -30,7 +30,7 @@ func (c *Client) GetIssueReactions(owner, repo string, index int64) ([]*Reaction
 | 
			
		||||
 | 
			
		||||
// GetIssueCommentReactions get a list of reactions from a comment of an issue
 | 
			
		||||
func (c *Client) GetIssueCommentReactions(owner, repo string, commentID int64) ([]*Reaction, *Response, error) {
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	reactions := make([]*Reaction, 0, 10)
 | 
			
		||||
@@ -45,7 +45,7 @@ type editReactionOption struct {
 | 
			
		||||
 | 
			
		||||
// PostIssueReaction add a reaction to an issue
 | 
			
		||||
func (c *Client) PostIssueReaction(owner, repo string, index int64, reaction string) (*Reaction, *Response, error) {
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	reactionResponse := new(Reaction)
 | 
			
		||||
@@ -61,7 +61,7 @@ func (c *Client) PostIssueReaction(owner, repo string, index int64, reaction str
 | 
			
		||||
 | 
			
		||||
// DeleteIssueReaction remove a reaction from an issue
 | 
			
		||||
func (c *Client) DeleteIssueReaction(owner, repo string, index int64, reaction string) (*Response, error) {
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(&editReactionOption{Reaction: reaction})
 | 
			
		||||
@@ -74,7 +74,7 @@ func (c *Client) DeleteIssueReaction(owner, repo string, index int64, reaction s
 | 
			
		||||
 | 
			
		||||
// PostIssueCommentReaction add a reaction to a comment of an issue
 | 
			
		||||
func (c *Client) PostIssueCommentReaction(owner, repo string, commentID int64, reaction string) (*Reaction, *Response, error) {
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	reactionResponse := new(Reaction)
 | 
			
		||||
@@ -90,7 +90,7 @@ func (c *Client) PostIssueCommentReaction(owner, repo string, commentID int64, r
 | 
			
		||||
 | 
			
		||||
// DeleteIssueCommentReaction remove a reaction from a comment of an issue
 | 
			
		||||
func (c *Client) DeleteIssueCommentReaction(owner, repo string, commentID int64, reaction string) (*Response, error) {
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(&editReactionOption{Reaction: reaction})
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								vendor/code.gitea.io/sdk/gitea/issue_stopwatch.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								vendor/code.gitea.io/sdk/gitea/issue_stopwatch.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -12,7 +12,12 @@ import (
 | 
			
		||||
// StopWatch represents a running stopwatch of an issue / pr
 | 
			
		||||
type StopWatch struct {
 | 
			
		||||
	Created       time.Time `json:"created"`
 | 
			
		||||
	Seconds       int64     `json:"seconds"`
 | 
			
		||||
	Duration      string    `json:"duration"`
 | 
			
		||||
	IssueIndex    int64     `json:"issue_index"`
 | 
			
		||||
	IssueTitle    string    `json:"issue_title"`
 | 
			
		||||
	RepoOwnerName string    `json:"repo_owner_name"`
 | 
			
		||||
	RepoName      string    `json:"repo_name"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetMyStopwatches list all stopwatches
 | 
			
		||||
@@ -24,6 +29,9 @@ func (c *Client) GetMyStopwatches() ([]*StopWatch, *Response, error) {
 | 
			
		||||
 | 
			
		||||
// DeleteIssueStopwatch delete / cancel a specific stopwatch
 | 
			
		||||
func (c *Client) DeleteIssueStopwatch(owner, repo string, index int64) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/delete", owner, repo, index), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
@@ -31,6 +39,9 @@ func (c *Client) DeleteIssueStopwatch(owner, repo string, index int64) (*Respons
 | 
			
		||||
// StartIssueStopWatch starts a stopwatch for an existing issue for a given
 | 
			
		||||
// repository
 | 
			
		||||
func (c *Client) StartIssueStopWatch(owner, repo string, index int64) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/start", owner, repo, index), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
@@ -38,6 +49,9 @@ func (c *Client) StartIssueStopWatch(owner, repo string, index int64) (*Response
 | 
			
		||||
// StopIssueStopWatch stops an existing stopwatch for an issue in a given
 | 
			
		||||
// repository
 | 
			
		||||
func (c *Client) StopIssueStopWatch(owner, repo string, index int64) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/stop", owner, repo, index), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								vendor/code.gitea.io/sdk/gitea/issue_subscription.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								vendor/code.gitea.io/sdk/gitea/issue_subscription.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -11,7 +11,7 @@ import (
 | 
			
		||||
 | 
			
		||||
// GetIssueSubscribers get list of users who subscribed on an issue
 | 
			
		||||
func (c *Client) GetIssueSubscribers(owner, repo string, index int64) ([]*User, *Response, error) {
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	subscribers := make([]*User, 0, 10)
 | 
			
		||||
@@ -21,7 +21,7 @@ func (c *Client) GetIssueSubscribers(owner, repo string, index int64) ([]*User,
 | 
			
		||||
 | 
			
		||||
// AddIssueSubscription Subscribe user to issue
 | 
			
		||||
func (c *Client) AddIssueSubscription(owner, repo string, index int64, user string) (*Response, error) {
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo, &user); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	status, resp, err := c.getStatusCode("PUT", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil)
 | 
			
		||||
@@ -39,7 +39,7 @@ func (c *Client) AddIssueSubscription(owner, repo string, index int64, user stri
 | 
			
		||||
 | 
			
		||||
// DeleteIssueSubscription unsubscribe user from issue
 | 
			
		||||
func (c *Client) DeleteIssueSubscription(owner, repo string, index int64, user string) (*Response, error) {
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo, &user); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil)
 | 
			
		||||
@@ -57,6 +57,9 @@ func (c *Client) DeleteIssueSubscription(owner, repo string, index int64, user s
 | 
			
		||||
 | 
			
		||||
// CheckIssueSubscription check if current user is subscribed to an issue
 | 
			
		||||
func (c *Client) CheckIssueSubscription(owner, repo string, index int64) (*WatchInfo, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										77
									
								
								vendor/code.gitea.io/sdk/gitea/issue_tracked_time.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										77
									
								
								vendor/code.gitea.io/sdk/gitea/issue_tracked_time.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -8,6 +8,7 @@ import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -25,33 +26,50 @@ type TrackedTime struct {
 | 
			
		||||
	Issue   *Issue `json:"issue"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetUserTrackedTimes list tracked times of a user
 | 
			
		||||
func (c *Client) GetUserTrackedTimes(owner, repo, user string) ([]*TrackedTime, *Response, error) {
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	times := make([]*TrackedTime, 0, 10)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/times/%s", owner, repo, user), nil, nil, ×)
 | 
			
		||||
	return times, resp, err
 | 
			
		||||
// ListTrackedTimesOptions options for listing repository's tracked times
 | 
			
		||||
type ListTrackedTimesOptions struct {
 | 
			
		||||
	ListOptions
 | 
			
		||||
	Since  time.Time
 | 
			
		||||
	Before time.Time
 | 
			
		||||
	// User filter is only used by ListRepoTrackedTimes !!!
 | 
			
		||||
	User string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetRepoTrackedTimes list tracked times of a repository
 | 
			
		||||
func (c *Client) GetRepoTrackedTimes(owner, repo string) ([]*TrackedTime, *Response, error) {
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
 | 
			
		||||
// QueryEncode turns options into querystring argument
 | 
			
		||||
func (opt *ListTrackedTimesOptions) QueryEncode() string {
 | 
			
		||||
	query := opt.getURLQuery()
 | 
			
		||||
 | 
			
		||||
	if !opt.Since.IsZero() {
 | 
			
		||||
		query.Add("since", opt.Since.Format(time.RFC3339))
 | 
			
		||||
	}
 | 
			
		||||
	if !opt.Before.IsZero() {
 | 
			
		||||
		query.Add("before", opt.Before.Format(time.RFC3339))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(opt.User) != 0 {
 | 
			
		||||
		query.Add("user", opt.User)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return query.Encode()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListRepoTrackedTimes list tracked times of a repository
 | 
			
		||||
func (c *Client) ListRepoTrackedTimes(owner, repo string, opt ListTrackedTimesOptions) ([]*TrackedTime, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	times := make([]*TrackedTime, 0, 10)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/times", owner, repo), nil, nil, ×)
 | 
			
		||||
	link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/times", owner, repo))
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	link.RawQuery = opt.QueryEncode()
 | 
			
		||||
	times := make([]*TrackedTime, 0, opt.PageSize)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, ×)
 | 
			
		||||
	return times, resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetMyTrackedTimes list tracked times of the current user
 | 
			
		||||
func (c *Client) GetMyTrackedTimes() ([]*TrackedTime, *Response, error) {
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	times := make([]*TrackedTime, 0, 10)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", "/user/times", nil, nil, ×)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", "/user/times", jsonHeader, nil, ×)
 | 
			
		||||
	return times, resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -75,7 +93,7 @@ func (opt AddTimeOption) Validate() error {
 | 
			
		||||
 | 
			
		||||
// AddTime adds time to issue with the given index
 | 
			
		||||
func (c *Client) AddTime(owner, repo string, index int64, opt AddTimeOption) (*TrackedTime, *Response, error) {
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := opt.Validate(); err != nil {
 | 
			
		||||
@@ -92,36 +110,33 @@ func (c *Client) AddTime(owner, repo string, index int64, opt AddTimeOption) (*T
 | 
			
		||||
	return t, resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListTrackedTimesOptions options for listing repository's tracked times
 | 
			
		||||
type ListTrackedTimesOptions struct {
 | 
			
		||||
	ListOptions
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListTrackedTimes list tracked times of a single issue for a given repository
 | 
			
		||||
func (c *Client) ListTrackedTimes(owner, repo string, index int64, opt ListTrackedTimesOptions) ([]*TrackedTime, *Response, error) {
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
 | 
			
		||||
// ListIssueTrackedTimes list tracked times of a single issue for a given repository
 | 
			
		||||
func (c *Client) ListIssueTrackedTimes(owner, repo string, index int64, opt ListTrackedTimesOptions) ([]*TrackedTime, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index))
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	link.RawQuery = opt.QueryEncode()
 | 
			
		||||
	times := make([]*TrackedTime, 0, opt.PageSize)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/times?%s", owner, repo, index, opt.getURLQuery().Encode()), nil, nil, ×)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, ×)
 | 
			
		||||
	return times, resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResetIssueTime reset tracked time of a single issue for a given repository
 | 
			
		||||
func (c *Client) ResetIssueTime(owner, repo string, index int64) (*Response, error) {
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index), nil, nil)
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index), jsonHeader, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteTime delete a specific tracked time by id of a single issue for a given repository
 | 
			
		||||
func (c *Client) DeleteTime(owner, repo string, index, timeID int64) (*Response, error) {
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times/%d", owner, repo, index, timeID), nil, nil)
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times/%d", owner, repo, index, timeID), jsonHeader, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								vendor/code.gitea.io/sdk/gitea/notifications.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								vendor/code.gitea.io/sdk/gitea/notifications.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -176,14 +176,17 @@ func (c *Client) ReadNotifications(opt MarkNotificationOptions) (*Response, erro
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListRepoNotifications list users's notification threads on a specific repo
 | 
			
		||||
func (c *Client) ListRepoNotifications(owner, reponame string, opt ListNotificationOptions) ([]*NotificationThread, *Response, error) {
 | 
			
		||||
func (c *Client) ListRepoNotifications(owner, repo string, opt ListNotificationOptions) ([]*NotificationThread, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := opt.Validate(c); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/notifications", owner, reponame))
 | 
			
		||||
	link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/notifications", owner, repo))
 | 
			
		||||
	link.RawQuery = opt.QueryEncode()
 | 
			
		||||
	threads := make([]*NotificationThread, 0, 10)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &threads)
 | 
			
		||||
@@ -191,14 +194,17 @@ func (c *Client) ListRepoNotifications(owner, reponame string, opt ListNotificat
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReadRepoNotifications mark notification threads as read on a specific repo
 | 
			
		||||
func (c *Client) ReadRepoNotifications(owner, reponame string, opt MarkNotificationOptions) (*Response, error) {
 | 
			
		||||
func (c *Client) ReadRepoNotifications(owner, repo string, opt MarkNotificationOptions) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := opt.Validate(c); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/notifications", owner, reponame))
 | 
			
		||||
	link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/notifications", owner, repo))
 | 
			
		||||
	link.RawQuery = opt.QueryEncode()
 | 
			
		||||
	_, resp, err := c.getResponse("PUT", link.String(), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								vendor/code.gitea.io/sdk/gitea/org.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								vendor/code.gitea.io/sdk/gitea/org.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -52,6 +52,9 @@ func (c *Client) ListMyOrgs(opt ListOrgsOptions) ([]*Organization, *Response, er
 | 
			
		||||
 | 
			
		||||
// ListUserOrgs list all of some user's organizations
 | 
			
		||||
func (c *Client) ListUserOrgs(user string, opt ListOrgsOptions) ([]*Organization, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	orgs := make([]*Organization, 0, opt.PageSize)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/orgs?%s", user, opt.getURLQuery().Encode()), nil, nil, &orgs)
 | 
			
		||||
@@ -60,6 +63,9 @@ func (c *Client) ListUserOrgs(user string, opt ListOrgsOptions) ([]*Organization
 | 
			
		||||
 | 
			
		||||
// GetOrg get one organization by name
 | 
			
		||||
func (c *Client) GetOrg(orgname string) (*Organization, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&orgname); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	org := new(Organization)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s", orgname), nil, nil, org)
 | 
			
		||||
	return org, resp, err
 | 
			
		||||
@@ -124,6 +130,9 @@ func (opt EditOrgOption) Validate() error {
 | 
			
		||||
 | 
			
		||||
// EditOrg modify one organization via options
 | 
			
		||||
func (c *Client) EditOrg(orgname string, opt EditOrgOption) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&orgname); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := opt.Validate(); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -137,6 +146,9 @@ func (c *Client) EditOrg(orgname string, opt EditOrgOption) (*Response, error) {
 | 
			
		||||
 | 
			
		||||
// DeleteOrg deletes an organization
 | 
			
		||||
func (c *Client) DeleteOrg(orgname string) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&orgname); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s", orgname), jsonHeader, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								vendor/code.gitea.io/sdk/gitea/org_member.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								vendor/code.gitea.io/sdk/gitea/org_member.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -12,7 +12,10 @@ import (
 | 
			
		||||
 | 
			
		||||
// DeleteOrgMembership remove a member from an organization
 | 
			
		||||
func (c *Client) DeleteOrgMembership(org, user string) (*Response, error) {
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil)
 | 
			
		||||
	if err := escapeValidatePathSegments(&org, &user); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/members/%s", org, user), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -23,10 +26,13 @@ type ListOrgMembershipOption struct {
 | 
			
		||||
 | 
			
		||||
// ListOrgMembership list an organization's members
 | 
			
		||||
func (c *Client) ListOrgMembership(org string, opt ListOrgMembershipOption) ([]*User, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&org); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	users := make([]*User, 0, opt.PageSize)
 | 
			
		||||
 | 
			
		||||
	link, _ := url.Parse(fmt.Sprintf("/orgs/%s/members", url.PathEscape(org)))
 | 
			
		||||
	link, _ := url.Parse(fmt.Sprintf("/orgs/%s/members", org))
 | 
			
		||||
	link.RawQuery = opt.getURLQuery().Encode()
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &users)
 | 
			
		||||
	return users, resp, err
 | 
			
		||||
@@ -34,10 +40,13 @@ func (c *Client) ListOrgMembership(org string, opt ListOrgMembershipOption) ([]*
 | 
			
		||||
 | 
			
		||||
// ListPublicOrgMembership list an organization's members
 | 
			
		||||
func (c *Client) ListPublicOrgMembership(org string, opt ListOrgMembershipOption) ([]*User, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&org); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	users := make([]*User, 0, opt.PageSize)
 | 
			
		||||
 | 
			
		||||
	link, _ := url.Parse(fmt.Sprintf("/orgs/%s/public_members", url.PathEscape(org)))
 | 
			
		||||
	link, _ := url.Parse(fmt.Sprintf("/orgs/%s/public_members", org))
 | 
			
		||||
	link.RawQuery = opt.getURLQuery().Encode()
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &users)
 | 
			
		||||
	return users, resp, err
 | 
			
		||||
@@ -45,7 +54,10 @@ func (c *Client) ListPublicOrgMembership(org string, opt ListOrgMembershipOption
 | 
			
		||||
 | 
			
		||||
// CheckOrgMembership Check if a user is a member of an organization
 | 
			
		||||
func (c *Client) CheckOrgMembership(org, user string) (bool, *Response, error) {
 | 
			
		||||
	status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil)
 | 
			
		||||
	if err := escapeValidatePathSegments(&org, &user); err != nil {
 | 
			
		||||
		return false, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/members/%s", org, user), nil, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, resp, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -61,7 +73,10 @@ func (c *Client) CheckOrgMembership(org, user string) (bool, *Response, error) {
 | 
			
		||||
 | 
			
		||||
// CheckPublicOrgMembership Check if a user is a member of an organization
 | 
			
		||||
func (c *Client) CheckPublicOrgMembership(org, user string) (bool, *Response, error) {
 | 
			
		||||
	status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/public_members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil)
 | 
			
		||||
	if err := escapeValidatePathSegments(&org, &user); err != nil {
 | 
			
		||||
		return false, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/public_members/%s", org, user), nil, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, resp, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -77,15 +92,18 @@ func (c *Client) CheckPublicOrgMembership(org, user string) (bool, *Response, er
 | 
			
		||||
 | 
			
		||||
// SetPublicOrgMembership publicize/conceal a user's membership
 | 
			
		||||
func (c *Client) SetPublicOrgMembership(org, user string, visible bool) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&org, &user); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	var (
 | 
			
		||||
		status int
 | 
			
		||||
		err    error
 | 
			
		||||
		resp   *Response
 | 
			
		||||
	)
 | 
			
		||||
	if visible {
 | 
			
		||||
		status, resp, err = c.getStatusCode("PUT", fmt.Sprintf("/orgs/%s/public_members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil)
 | 
			
		||||
		status, resp, err = c.getStatusCode("PUT", fmt.Sprintf("/orgs/%s/public_members/%s", org, user), nil, nil)
 | 
			
		||||
	} else {
 | 
			
		||||
		status, resp, err = c.getStatusCode("DELETE", fmt.Sprintf("/orgs/%s/public_members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil)
 | 
			
		||||
		status, resp, err = c.getStatusCode("DELETE", fmt.Sprintf("/orgs/%s/public_members/%s", org, user), nil, nil)
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return resp, err
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								vendor/code.gitea.io/sdk/gitea/org_team.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								vendor/code.gitea.io/sdk/gitea/org_team.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -30,6 +30,9 @@ type ListTeamsOptions struct {
 | 
			
		||||
 | 
			
		||||
// ListOrgTeams lists all teams of an organization
 | 
			
		||||
func (c *Client) ListOrgTeams(org string, opt ListTeamsOptions) ([]*Team, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&org); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	teams := make([]*Team, 0, opt.PageSize)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/teams?%s", org, opt.getURLQuery().Encode()), nil, nil, &teams)
 | 
			
		||||
@@ -83,6 +86,9 @@ func (opt CreateTeamOption) Validate() error {
 | 
			
		||||
 | 
			
		||||
// CreateTeam creates a team for an organization
 | 
			
		||||
func (c *Client) CreateTeam(org string, opt CreateTeamOption) (*Team, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&org); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := opt.Validate(); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -159,6 +165,9 @@ func (c *Client) ListTeamMembers(id int64, opt ListTeamMembersOptions) ([]*User,
 | 
			
		||||
 | 
			
		||||
// GetTeamMember gets a member of a team
 | 
			
		||||
func (c *Client) GetTeamMember(id int64, user string) (*User, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	m := new(User)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil, m)
 | 
			
		||||
	return m, resp, err
 | 
			
		||||
@@ -166,12 +175,18 @@ func (c *Client) GetTeamMember(id int64, user string) (*User, *Response, error)
 | 
			
		||||
 | 
			
		||||
// AddTeamMember adds a member to a team
 | 
			
		||||
func (c *Client) AddTeamMember(id int64, user string) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("PUT", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RemoveTeamMember removes a member from a team
 | 
			
		||||
func (c *Client) RemoveTeamMember(id int64, user string) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
@@ -191,12 +206,18 @@ func (c *Client) ListTeamRepositories(id int64, opt ListTeamRepositoriesOptions)
 | 
			
		||||
 | 
			
		||||
// AddTeamRepository adds a repository to a team
 | 
			
		||||
func (c *Client) AddTeamRepository(id int64, org, repo string) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&org, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("PUT", fmt.Sprintf("/teams/%d/repos/%s/%s", id, org, repo), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RemoveTeamRepository removes a repository from a team
 | 
			
		||||
func (c *Client) RemoveTeamRepository(id int64, org, repo string) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&org, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d/repos/%s/%s", id, org, repo), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										53
									
								
								vendor/code.gitea.io/sdk/gitea/pull.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										53
									
								
								vendor/code.gitea.io/sdk/gitea/pull.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -99,19 +99,37 @@ func (opt *ListPullRequestsOptions) QueryEncode() string {
 | 
			
		||||
 | 
			
		||||
// ListRepoPullRequests list PRs of one repository
 | 
			
		||||
func (c *Client) ListRepoPullRequests(owner, repo string, opt ListPullRequestsOptions) ([]*PullRequest, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	prs := make([]*PullRequest, 0, opt.PageSize)
 | 
			
		||||
 | 
			
		||||
	link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls", owner, repo))
 | 
			
		||||
	link.RawQuery = opt.QueryEncode()
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &prs)
 | 
			
		||||
	if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil {
 | 
			
		||||
		for i := range prs {
 | 
			
		||||
			if err := fixPullHeadSha(c, prs[i]); err != nil {
 | 
			
		||||
				return prs, resp, err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return prs, resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetPullRequest get information of one PR
 | 
			
		||||
func (c *Client) GetPullRequest(owner, repo string, index int64) (*PullRequest, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	pr := new(PullRequest)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d", owner, repo, index), nil, nil, pr)
 | 
			
		||||
	if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil {
 | 
			
		||||
		if err := fixPullHeadSha(c, pr); err != nil {
 | 
			
		||||
			return pr, resp, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return pr, resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -130,6 +148,9 @@ type CreatePullRequestOption struct {
 | 
			
		||||
 | 
			
		||||
// CreatePullRequest create pull request with options
 | 
			
		||||
func (c *Client) CreatePullRequest(owner, repo string, opt CreatePullRequestOption) (*PullRequest, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(&opt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
@@ -169,6 +190,9 @@ func (opt EditPullRequestOption) Validate(c *Client) error {
 | 
			
		||||
 | 
			
		||||
// EditPullRequest modify pull request with PR id and options
 | 
			
		||||
func (c *Client) EditPullRequest(owner, repo string, index int64, opt EditPullRequestOption) (*PullRequest, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := opt.Validate(c); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -202,6 +226,9 @@ func (opt MergePullRequestOption) Validate(c *Client) error {
 | 
			
		||||
 | 
			
		||||
// MergePullRequest merge a PR to repository by PR id
 | 
			
		||||
func (c *Client) MergePullRequest(owner, repo string, index int64, opt MergePullRequestOption) (bool, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return false, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := opt.Validate(c); err != nil {
 | 
			
		||||
		return false, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -218,6 +245,9 @@ func (c *Client) MergePullRequest(owner, repo string, index int64, opt MergePull
 | 
			
		||||
 | 
			
		||||
// IsPullRequestMerged test if one PR is merged to one repository
 | 
			
		||||
func (c *Client) IsPullRequestMerged(owner, repo string, index int64) (bool, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return false, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d/merge", owner, repo, index), nil, nil)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -229,6 +259,9 @@ func (c *Client) IsPullRequestMerged(owner, repo string, index int64) (bool, *Re
 | 
			
		||||
 | 
			
		||||
// getPullRequestDiffOrPatch gets the patch or diff file as bytes for a PR
 | 
			
		||||
func (c *Client) getPullRequestDiffOrPatch(owner, repo, kind string, index int64) ([]byte, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo, &kind); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
 | 
			
		||||
		r, _, err2 := c.GetRepo(owner, repo)
 | 
			
		||||
		if err2 != nil {
 | 
			
		||||
@@ -251,3 +284,23 @@ func (c *Client) GetPullRequestPatch(owner, repo string, index int64) ([]byte, *
 | 
			
		||||
func (c *Client) GetPullRequestDiff(owner, repo string, index int64) ([]byte, *Response, error) {
 | 
			
		||||
	return c.getPullRequestDiffOrPatch(owner, repo, "diff", index)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// fixPullHeadSha is a workaround for https://github.com/go-gitea/gitea/issues/12675
 | 
			
		||||
// When no head sha is available, this is because the branch got deleted in the base repo.
 | 
			
		||||
// pr.Head.Ref points in this case not to the head repo branch name, but the base repo ref,
 | 
			
		||||
// which stays available to resolve the commit sha. This is fixed for gitea >= 1.14.0
 | 
			
		||||
func fixPullHeadSha(client *Client, pr *PullRequest) error {
 | 
			
		||||
	if pr.Base != nil && pr.Base.Repository != nil && pr.Base.Repository.Owner != nil &&
 | 
			
		||||
		pr.Head != nil && pr.Head.Ref != "" && pr.Head.Sha == "" {
 | 
			
		||||
		owner := pr.Base.Repository.Owner.UserName
 | 
			
		||||
		repo := pr.Base.Repository.Name
 | 
			
		||||
		refs, _, err := client.GetRepoRefs(owner, repo, pr.Head.Ref)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		} else if len(refs) == 0 {
 | 
			
		||||
			return fmt.Errorf("unable to resolve PR ref '%s'", pr.Head.Ref)
 | 
			
		||||
		}
 | 
			
		||||
		pr.Head.Sha = refs[0].Object.SHA
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										105
									
								
								vendor/code.gitea.io/sdk/gitea/pull_review.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										105
									
								
								vendor/code.gitea.io/sdk/gitea/pull_review.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -35,11 +35,15 @@ const (
 | 
			
		||||
type PullReview struct {
 | 
			
		||||
	ID           int64           `json:"id"`
 | 
			
		||||
	Reviewer     *User           `json:"user"`
 | 
			
		||||
	ReviewerTeam *Team           `json:"team"`
 | 
			
		||||
	State        ReviewStateType `json:"state"`
 | 
			
		||||
	Body         string          `json:"body"`
 | 
			
		||||
	CommitID     string          `json:"commit_id"`
 | 
			
		||||
	// Stale indicates if the pull has changed since the review
 | 
			
		||||
	Stale bool `json:"stale"`
 | 
			
		||||
	// Official indicates if the review counts towards the required approval limit, if PR base is a protected branch
 | 
			
		||||
	Official          bool      `json:"official"`
 | 
			
		||||
	Dismissed         bool      `json:"dismissed"`
 | 
			
		||||
	CodeCommentsCount int       `json:"comments_count"`
 | 
			
		||||
	Submitted         time.Time `json:"submitted_at"`
 | 
			
		||||
 | 
			
		||||
@@ -93,6 +97,17 @@ type SubmitPullReviewOptions struct {
 | 
			
		||||
	Body  string          `json:"body"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DismissPullReviewOptions are options to dismiss a pull review
 | 
			
		||||
type DismissPullReviewOptions struct {
 | 
			
		||||
	Message string `json:"message"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PullReviewRequestOptions are options to add or remove pull review requests
 | 
			
		||||
type PullReviewRequestOptions struct {
 | 
			
		||||
	Reviewers     []string `json:"reviewers"`
 | 
			
		||||
	TeamReviewers []string `json:"team_reviewers"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListPullReviewsOptions options for listing PullReviews
 | 
			
		||||
type ListPullReviewsOptions struct {
 | 
			
		||||
	ListOptions
 | 
			
		||||
@@ -132,6 +147,9 @@ func (opt CreatePullReviewComment) Validate() error {
 | 
			
		||||
 | 
			
		||||
// ListPullReviews lists all reviews of a pull request
 | 
			
		||||
func (c *Client) ListPullReviews(owner, repo string, index int64, opt ListPullReviewsOptions) ([]*PullReview, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -147,6 +165,9 @@ func (c *Client) ListPullReviews(owner, repo string, index int64, opt ListPullRe
 | 
			
		||||
 | 
			
		||||
// GetPullReview gets a specific review of a pull request
 | 
			
		||||
func (c *Client) GetPullReview(owner, repo string, index, id int64) (*PullReview, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -158,6 +179,9 @@ func (c *Client) GetPullReview(owner, repo string, index, id int64) (*PullReview
 | 
			
		||||
 | 
			
		||||
// ListPullReviewComments lists all comments of a pull request review
 | 
			
		||||
func (c *Client) ListPullReviewComments(owner, repo string, index, id int64) ([]*PullReviewComment, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -170,6 +194,9 @@ func (c *Client) ListPullReviewComments(owner, repo string, index, id int64) ([]
 | 
			
		||||
 | 
			
		||||
// DeletePullReview delete a specific review from a pull request
 | 
			
		||||
func (c *Client) DeletePullReview(owner, repo string, index, id int64) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -180,6 +207,9 @@ func (c *Client) DeletePullReview(owner, repo string, index, id int64) (*Respons
 | 
			
		||||
 | 
			
		||||
// CreatePullReview create a review to an pull request
 | 
			
		||||
func (c *Client) CreatePullReview(owner, repo string, index int64, opt CreatePullReviewOptions) (*PullReview, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -200,6 +230,9 @@ func (c *Client) CreatePullReview(owner, repo string, index int64, opt CreatePul
 | 
			
		||||
 | 
			
		||||
// SubmitPullReview submit a pending review to an pull request
 | 
			
		||||
func (c *Client) SubmitPullReview(owner, repo string, index, id int64, opt SubmitPullReviewOptions) (*PullReview, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -217,3 +250,75 @@ func (c *Client) SubmitPullReview(owner, repo string, index, id int64, opt Submi
 | 
			
		||||
		jsonHeader, bytes.NewReader(body), r)
 | 
			
		||||
	return r, resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateReviewRequests create review requests to an pull request
 | 
			
		||||
func (c *Client) CreateReviewRequests(owner, repo string, index int64, opt PullReviewRequestOptions) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(&opt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, resp, err := c.getResponse("POST",
 | 
			
		||||
		fmt.Sprintf("/repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, index),
 | 
			
		||||
		jsonHeader, bytes.NewReader(body))
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteReviewRequests delete review requests to an pull request
 | 
			
		||||
func (c *Client) DeleteReviewRequests(owner, repo string, index int64, opt PullReviewRequestOptions) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(&opt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE",
 | 
			
		||||
		fmt.Sprintf("/repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, index),
 | 
			
		||||
		jsonHeader, bytes.NewReader(body))
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DismissPullReview dismiss a review for a pull request
 | 
			
		||||
func (c *Client) DismissPullReview(owner, repo string, index, id int64, opt DismissPullReviewOptions) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(&opt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, resp, err := c.getResponse("POST",
 | 
			
		||||
		fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d/dismissals", owner, repo, index, id),
 | 
			
		||||
		jsonHeader, bytes.NewReader(body))
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnDismissPullReview cancel to dismiss a review for a pull request
 | 
			
		||||
func (c *Client) UnDismissPullReview(owner, repo string, index, id int64) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, resp, err := c.getResponse("POST",
 | 
			
		||||
		fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d/undismissals", owner, repo, index, id),
 | 
			
		||||
		jsonHeader, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										61
									
								
								vendor/code.gitea.io/sdk/gitea/release.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										61
									
								
								vendor/code.gitea.io/sdk/gitea/release.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -21,6 +21,7 @@ type Release struct {
 | 
			
		||||
	Title        string        `json:"name"`
 | 
			
		||||
	Note         string        `json:"body"`
 | 
			
		||||
	URL          string        `json:"url"`
 | 
			
		||||
	HTMLURL      string        `json:"html_url"`
 | 
			
		||||
	TarURL       string        `json:"tarball_url"`
 | 
			
		||||
	ZipURL       string        `json:"zipball_url"`
 | 
			
		||||
	IsDraft      bool          `json:"draft"`
 | 
			
		||||
@@ -37,32 +38,41 @@ type ListReleasesOptions struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListReleases list releases of a repository
 | 
			
		||||
func (c *Client) ListReleases(user, repo string, opt ListReleasesOptions) ([]*Release, *Response, error) {
 | 
			
		||||
func (c *Client) ListReleases(owner, repo string, opt ListReleasesOptions) ([]*Release, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	releases := make([]*Release, 0, opt.PageSize)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET",
 | 
			
		||||
		fmt.Sprintf("/repos/%s/%s/releases?%s", user, repo, opt.getURLQuery().Encode()),
 | 
			
		||||
		fmt.Sprintf("/repos/%s/%s/releases?%s", owner, repo, opt.getURLQuery().Encode()),
 | 
			
		||||
		nil, nil, &releases)
 | 
			
		||||
	return releases, resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetRelease get a release of a repository by id
 | 
			
		||||
func (c *Client) GetRelease(user, repo string, id int64) (*Release, *Response, error) {
 | 
			
		||||
func (c *Client) GetRelease(owner, repo string, id int64) (*Release, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	r := new(Release)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET",
 | 
			
		||||
		fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id),
 | 
			
		||||
		fmt.Sprintf("/repos/%s/%s/releases/%d", owner, repo, id),
 | 
			
		||||
		jsonHeader, nil, &r)
 | 
			
		||||
	return r, resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetReleaseByTag get a release of a repository by tag
 | 
			
		||||
func (c *Client) GetReleaseByTag(user, repo string, tag string) (*Release, *Response, error) {
 | 
			
		||||
func (c *Client) GetReleaseByTag(owner, repo string, tag string) (*Release, *Response, error) {
 | 
			
		||||
	if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil {
 | 
			
		||||
		return c.fallbackGetReleaseByTag(user, repo, tag)
 | 
			
		||||
		return c.fallbackGetReleaseByTag(owner, repo, tag)
 | 
			
		||||
	}
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo, &tag); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	r := new(Release)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET",
 | 
			
		||||
		fmt.Sprintf("/repos/%s/%s/releases/tags/%s", user, repo, tag),
 | 
			
		||||
		fmt.Sprintf("/repos/%s/%s/releases/tags/%s", owner, repo, tag),
 | 
			
		||||
		nil, nil, &r)
 | 
			
		||||
	return r, resp, err
 | 
			
		||||
}
 | 
			
		||||
@@ -86,7 +96,10 @@ func (opt CreateReleaseOption) Validate() error {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateRelease create a release
 | 
			
		||||
func (c *Client) CreateRelease(user, repo string, opt CreateReleaseOption) (*Release, *Response, error) {
 | 
			
		||||
func (c *Client) CreateRelease(owner, repo string, opt CreateReleaseOption) (*Release, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := opt.Validate(); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -96,7 +109,7 @@ func (c *Client) CreateRelease(user, repo string, opt CreateReleaseOption) (*Rel
 | 
			
		||||
	}
 | 
			
		||||
	r := new(Release)
 | 
			
		||||
	resp, err := c.getParsedResponse("POST",
 | 
			
		||||
		fmt.Sprintf("/repos/%s/%s/releases", user, repo),
 | 
			
		||||
		fmt.Sprintf("/repos/%s/%s/releases", owner, repo),
 | 
			
		||||
		jsonHeader, bytes.NewReader(body), r)
 | 
			
		||||
	return r, resp, err
 | 
			
		||||
}
 | 
			
		||||
@@ -112,30 +125,50 @@ type EditReleaseOption struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EditRelease edit a release
 | 
			
		||||
func (c *Client) EditRelease(user, repo string, id int64, form EditReleaseOption) (*Release, *Response, error) {
 | 
			
		||||
func (c *Client) EditRelease(owner, repo string, id int64, form EditReleaseOption) (*Release, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(form)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	r := new(Release)
 | 
			
		||||
	resp, err := c.getParsedResponse("PATCH",
 | 
			
		||||
		fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id),
 | 
			
		||||
		fmt.Sprintf("/repos/%s/%s/releases/%d", owner, repo, id),
 | 
			
		||||
		jsonHeader, bytes.NewReader(body), r)
 | 
			
		||||
	return r, resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteRelease delete a release from a repository
 | 
			
		||||
// DeleteRelease delete a release from a repository, keeping its tag
 | 
			
		||||
func (c *Client) DeleteRelease(user, repo string, id int64) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE",
 | 
			
		||||
		fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id),
 | 
			
		||||
		nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteReleaseByTag deletes a release frm a repository by tag
 | 
			
		||||
func (c *Client) DeleteReleaseByTag(user, repo string, tag string) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo, &tag); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE",
 | 
			
		||||
		fmt.Sprintf("/repos/%s/%s/releases/tags/%s", user, repo, tag),
 | 
			
		||||
		nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// fallbackGetReleaseByTag is fallback for old gitea installations ( < 1.13.0 )
 | 
			
		||||
func (c *Client) fallbackGetReleaseByTag(user, repo string, tag string) (*Release, *Response, error) {
 | 
			
		||||
func (c *Client) fallbackGetReleaseByTag(owner, repo string, tag string) (*Release, *Response, error) {
 | 
			
		||||
	for i := 1; ; i++ {
 | 
			
		||||
		rl, resp, err := c.ListReleases(user, repo, ListReleasesOptions{ListOptions{Page: i}})
 | 
			
		||||
		rl, resp, err := c.ListReleases(owner, repo, ListReleasesOptions{ListOptions{Page: i}})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, resp, err
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										99
									
								
								vendor/code.gitea.io/sdk/gitea/repo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										99
									
								
								vendor/code.gitea.io/sdk/gitea/repo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -9,6 +9,7 @@ import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
@@ -21,6 +22,32 @@ type Permission struct {
 | 
			
		||||
	Pull  bool `json:"pull"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InternalTracker represents settings for internal tracker
 | 
			
		||||
type InternalTracker struct {
 | 
			
		||||
	// Enable time tracking (Built-in issue tracker)
 | 
			
		||||
	EnableTimeTracker bool `json:"enable_time_tracker"`
 | 
			
		||||
	// Let only contributors track time (Built-in issue tracker)
 | 
			
		||||
	AllowOnlyContributorsToTrackTime bool `json:"allow_only_contributors_to_track_time"`
 | 
			
		||||
	// Enable dependencies for issues and pull requests (Built-in issue tracker)
 | 
			
		||||
	EnableIssueDependencies bool `json:"enable_issue_dependencies"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExternalTracker represents settings for external tracker
 | 
			
		||||
type ExternalTracker struct {
 | 
			
		||||
	// URL of external issue tracker.
 | 
			
		||||
	ExternalTrackerURL string `json:"external_tracker_url"`
 | 
			
		||||
	// External Issue Tracker URL Format. Use the placeholders {user}, {repo} and {index} for the username, repository name and issue index.
 | 
			
		||||
	ExternalTrackerFormat string `json:"external_tracker_format"`
 | 
			
		||||
	// External Issue Tracker Number Format, either `numeric` or `alphanumeric`
 | 
			
		||||
	ExternalTrackerStyle string `json:"external_tracker_style"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExternalWiki represents setting for external wiki
 | 
			
		||||
type ExternalWiki struct {
 | 
			
		||||
	// URL of external wiki.
 | 
			
		||||
	ExternalWikiURL string `json:"external_wiki_url"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Repository represents a repository
 | 
			
		||||
type Repository struct {
 | 
			
		||||
	ID                        int64            `json:"id"`
 | 
			
		||||
@@ -31,6 +58,7 @@ type Repository struct {
 | 
			
		||||
	Empty                     bool             `json:"empty"`
 | 
			
		||||
	Private                   bool             `json:"private"`
 | 
			
		||||
	Fork                      bool             `json:"fork"`
 | 
			
		||||
	Template                  bool             `json:"template"`
 | 
			
		||||
	Parent                    *Repository      `json:"parent"`
 | 
			
		||||
	Mirror                    bool             `json:"mirror"`
 | 
			
		||||
	Size                      int              `json:"size"`
 | 
			
		||||
@@ -43,20 +71,28 @@ type Repository struct {
 | 
			
		||||
	Forks                     int              `json:"forks_count"`
 | 
			
		||||
	Watchers                  int              `json:"watchers_count"`
 | 
			
		||||
	OpenIssues                int              `json:"open_issues_count"`
 | 
			
		||||
	OpenPulls                 int              `json:"open_pr_counter"`
 | 
			
		||||
	Releases                  int              `json:"release_counter"`
 | 
			
		||||
	DefaultBranch             string           `json:"default_branch"`
 | 
			
		||||
	Archived                  bool             `json:"archived"`
 | 
			
		||||
	Created                   time.Time        `json:"created_at"`
 | 
			
		||||
	Updated                   time.Time        `json:"updated_at"`
 | 
			
		||||
	Permissions               *Permission      `json:"permissions,omitempty"`
 | 
			
		||||
	HasIssues                 bool             `json:"has_issues"`
 | 
			
		||||
	InternalTracker           *InternalTracker `json:"internal_tracker,omitempty"`
 | 
			
		||||
	ExternalTracker           *ExternalTracker `json:"external_tracker,omitempty"`
 | 
			
		||||
	HasWiki                   bool             `json:"has_wiki"`
 | 
			
		||||
	ExternalWiki              *ExternalWiki    `json:"external_wiki,omitempty"`
 | 
			
		||||
	HasPullRequests           bool             `json:"has_pull_requests"`
 | 
			
		||||
	HasProjects               bool             `json:"has_projects"`
 | 
			
		||||
	IgnoreWhitespaceConflicts bool             `json:"ignore_whitespace_conflicts"`
 | 
			
		||||
	AllowMerge                bool             `json:"allow_merge_commits"`
 | 
			
		||||
	AllowRebase               bool             `json:"allow_rebase"`
 | 
			
		||||
	AllowRebaseMerge          bool             `json:"allow_rebase_explicit"`
 | 
			
		||||
	AllowSquash               bool             `json:"allow_squash_merge"`
 | 
			
		||||
	AvatarURL                 string           `json:"avatar_url"`
 | 
			
		||||
	Internal                  bool             `json:"internal"`
 | 
			
		||||
	MirrorInterval            string           `json:"mirror_interval"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RepoType represent repo type
 | 
			
		||||
@@ -102,6 +138,9 @@ func (c *Client) ListMyRepos(opt ListReposOptions) ([]*Repository, *Response, er
 | 
			
		||||
 | 
			
		||||
// ListUserRepos list all repositories of one user by user's name
 | 
			
		||||
func (c *Client) ListUserRepos(user string, opt ListReposOptions) ([]*Repository, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	repos := make([]*Repository, 0, opt.PageSize)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/repos?%s", user, opt.getURLQuery().Encode()), nil, nil, &repos)
 | 
			
		||||
@@ -115,6 +154,9 @@ type ListOrgReposOptions struct {
 | 
			
		||||
 | 
			
		||||
// ListOrgRepos list all repositories of one organization by organization's name
 | 
			
		||||
func (c *Client) ListOrgRepos(org string, opt ListOrgReposOptions) ([]*Repository, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&org); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	repos := make([]*Repository, 0, opt.PageSize)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/repos?%s", org, opt.getURLQuery().Encode()), nil, nil, &repos)
 | 
			
		||||
@@ -315,6 +357,9 @@ func (c *Client) CreateRepo(opt CreateRepoOption) (*Repository, *Response, error
 | 
			
		||||
 | 
			
		||||
// CreateOrgRepo creates an organization repository for authenticated user.
 | 
			
		||||
func (c *Client) CreateOrgRepo(org string, opt CreateRepoOption) (*Repository, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&org); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := opt.Validate(c); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -329,6 +374,9 @@ func (c *Client) CreateOrgRepo(org string, opt CreateRepoOption) (*Repository, *
 | 
			
		||||
 | 
			
		||||
// GetRepo returns information of a repository of given owner.
 | 
			
		||||
func (c *Client) GetRepo(owner, reponame string) (*Repository, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &reponame); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	repo := new(Repository)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s", owner, reponame), nil, nil, repo)
 | 
			
		||||
	return repo, resp, err
 | 
			
		||||
@@ -346,14 +394,24 @@ type EditRepoOption struct {
 | 
			
		||||
	// Note: you will get a 422 error if the organization restricts changing repository visibility to organization
 | 
			
		||||
	// owners and a non-owner tries to change the value of private.
 | 
			
		||||
	Private *bool `json:"private,omitempty"`
 | 
			
		||||
	// either `true` to make this repository a template or `false` to make it a normal repository
 | 
			
		||||
	Template *bool `json:"template,omitempty"`
 | 
			
		||||
	// either `true` to enable issues for this repository or `false` to disable them.
 | 
			
		||||
	HasIssues *bool `json:"has_issues,omitempty"`
 | 
			
		||||
	// set this structure to configure internal issue tracker (requires has_issues)
 | 
			
		||||
	InternalTracker *InternalTracker `json:"internal_tracker,omitempty"`
 | 
			
		||||
	// set this structure to use external issue tracker (requires has_issues)
 | 
			
		||||
	ExternalTracker *ExternalTracker `json:"external_tracker,omitempty"`
 | 
			
		||||
	// either `true` to enable the wiki for this repository or `false` to disable it.
 | 
			
		||||
	HasWiki *bool `json:"has_wiki,omitempty"`
 | 
			
		||||
	// set this structure to use external wiki instead of internal (requires has_wiki)
 | 
			
		||||
	ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"`
 | 
			
		||||
	// sets the default branch for this repository.
 | 
			
		||||
	DefaultBranch *string `json:"default_branch,omitempty"`
 | 
			
		||||
	// either `true` to allow pull requests, or `false` to prevent pull request.
 | 
			
		||||
	HasPullRequests *bool `json:"has_pull_requests,omitempty"`
 | 
			
		||||
	// either `true` to enable project unit, or `false` to disable them.
 | 
			
		||||
	HasProjects *bool `json:"has_projects,omitempty"`
 | 
			
		||||
	// either `true` to ignore whitespace for conflicts, or `false` to not ignore whitespace. `has_pull_requests` must be `true`.
 | 
			
		||||
	IgnoreWhitespaceConflicts *bool `json:"ignore_whitespace_conflicts,omitempty"`
 | 
			
		||||
	// either `true` to allow merging pull requests with a merge commit, or `false` to prevent merging pull requests with merge commits. `has_pull_requests` must be `true`.
 | 
			
		||||
@@ -366,10 +424,15 @@ type EditRepoOption struct {
 | 
			
		||||
	AllowSquash *bool `json:"allow_squash_merge,omitempty"`
 | 
			
		||||
	// set to `true` to archive this repository.
 | 
			
		||||
	Archived *bool `json:"archived,omitempty"`
 | 
			
		||||
	// set to a string like `8h30m0s` to set the mirror interval time
 | 
			
		||||
	MirrorInterval *string `json:"mirror_interval,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EditRepo edit the properties of a repository
 | 
			
		||||
func (c *Client) EditRepo(owner, reponame string, opt EditRepoOption) (*Repository, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &reponame); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := json.Marshal(&opt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
@@ -381,18 +444,27 @@ func (c *Client) EditRepo(owner, reponame string, opt EditRepoOption) (*Reposito
 | 
			
		||||
 | 
			
		||||
// DeleteRepo deletes a repository of user or organization.
 | 
			
		||||
func (c *Client) DeleteRepo(owner, repo string) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s", owner, repo), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MirrorSync adds a mirrored repository to the mirror sync queue.
 | 
			
		||||
func (c *Client) MirrorSync(owner, repo string) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	_, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/mirror-sync", owner, repo), nil, nil)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetRepoLanguages return language stats of a repo
 | 
			
		||||
func (c *Client) GetRepoLanguages(owner, repo string) (map[string]int64, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	langMap := make(map[string]int64)
 | 
			
		||||
 | 
			
		||||
	data, resp, err := c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/languages", owner, repo), jsonHeader, nil)
 | 
			
		||||
@@ -418,5 +490,30 @@ const (
 | 
			
		||||
// GetArchive get an archive of a repository by git reference
 | 
			
		||||
// e.g.: ref -> master, 70b7c74b33, v1.2.1, ...
 | 
			
		||||
func (c *Client) GetArchive(owner, repo, ref string, ext ArchiveType) ([]byte, *Response, error) {
 | 
			
		||||
	return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/archive/%s%s", owner, repo, url.PathEscape(ref), ext), nil, nil)
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	ref = pathEscapeSegments(ref)
 | 
			
		||||
	return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/archive/%s%s", owner, repo, ref, ext), nil, nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetArchiveReader gets a `git archive` for a particular tree-ish git reference
 | 
			
		||||
// such as a branch name (`master`), a commit hash (`70b7c74b33`), a tag
 | 
			
		||||
// (`v1.2.1`). The archive is returned as a byte stream in a ReadCloser. It is
 | 
			
		||||
// the responsibility of the client to close the reader.
 | 
			
		||||
func (c *Client) GetArchiveReader(owner, repo, ref string, ext ArchiveType) (io.ReadCloser, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	ref = pathEscapeSegments(ref)
 | 
			
		||||
	resp, err := c.doRequest("GET", fmt.Sprintf("/repos/%s/%s/archive/%s%s", owner, repo, ref, ext), nil, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, resp, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, err := statusCodeToErr(resp); err != nil {
 | 
			
		||||
		return nil, resp, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return resp.Body, resp, nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								vendor/code.gitea.io/sdk/gitea/repo_branch.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								vendor/code.gitea.io/sdk/gitea/repo_branch.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -20,9 +20,6 @@ type PayloadUser struct {
 | 
			
		||||
	UserName string `json:"username"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FIXME: consider using same format as API when commits API are added.
 | 
			
		||||
//        applies to PayloadCommit and PayloadCommitVerification
 | 
			
		||||
 | 
			
		||||
// PayloadCommit represents a commit
 | 
			
		||||
type PayloadCommit struct {
 | 
			
		||||
	// sha1 hash of the commit
 | 
			
		||||
@@ -66,6 +63,9 @@ type ListRepoBranchesOptions struct {
 | 
			
		||||
 | 
			
		||||
// ListRepoBranches list all the branches of one repository
 | 
			
		||||
func (c *Client) ListRepoBranches(user, repo string, opt ListRepoBranchesOptions) ([]*Branch, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	opt.setDefaults()
 | 
			
		||||
	branches := make([]*Branch, 0, opt.PageSize)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &branches)
 | 
			
		||||
@@ -74,6 +74,9 @@ func (c *Client) ListRepoBranches(user, repo string, opt ListRepoBranchesOptions
 | 
			
		||||
 | 
			
		||||
// GetRepoBranch get one branch's information of one repository
 | 
			
		||||
func (c *Client) GetRepoBranch(user, repo, branch string) (*Branch, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo, &branch); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	b := new(Branch)
 | 
			
		||||
	resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil, &b)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -84,6 +87,9 @@ func (c *Client) GetRepoBranch(user, repo, branch string) (*Branch, *Response, e
 | 
			
		||||
 | 
			
		||||
// DeleteRepoBranch delete a branch in a repository
 | 
			
		||||
func (c *Client) DeleteRepoBranch(user, repo, branch string) (bool, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&user, &repo, &branch); err != nil {
 | 
			
		||||
		return false, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
 | 
			
		||||
		return false, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -118,6 +124,9 @@ func (opt CreateBranchOption) Validate() error {
 | 
			
		||||
 | 
			
		||||
// CreateBranch creates a branch for a user's repository
 | 
			
		||||
func (c *Client) CreateBranch(owner, repo string, opt CreateBranchOption) (*Branch, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								vendor/code.gitea.io/sdk/gitea/repo_branch_protection.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								vendor/code.gitea.io/sdk/gitea/repo_branch_protection.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -30,6 +30,7 @@ type BranchProtection struct {
 | 
			
		||||
	ApprovalsWhitelistUsernames   []string  `json:"approvals_whitelist_username"`
 | 
			
		||||
	ApprovalsWhitelistTeams       []string  `json:"approvals_whitelist_teams"`
 | 
			
		||||
	BlockOnRejectedReviews        bool      `json:"block_on_rejected_reviews"`
 | 
			
		||||
	BlockOnOfficialReviewRequests bool      `json:"block_on_official_review_requests"`
 | 
			
		||||
	BlockOnOutdatedBranch         bool      `json:"block_on_outdated_branch"`
 | 
			
		||||
	DismissStaleApprovals         bool      `json:"dismiss_stale_approvals"`
 | 
			
		||||
	RequireSignedCommits          bool      `json:"require_signed_commits"`
 | 
			
		||||
@@ -56,6 +57,7 @@ type CreateBranchProtectionOption struct {
 | 
			
		||||
	ApprovalsWhitelistUsernames   []string `json:"approvals_whitelist_username"`
 | 
			
		||||
	ApprovalsWhitelistTeams       []string `json:"approvals_whitelist_teams"`
 | 
			
		||||
	BlockOnRejectedReviews        bool     `json:"block_on_rejected_reviews"`
 | 
			
		||||
	BlockOnOfficialReviewRequests bool     `json:"block_on_official_review_requests"`
 | 
			
		||||
	BlockOnOutdatedBranch         bool     `json:"block_on_outdated_branch"`
 | 
			
		||||
	DismissStaleApprovals         bool     `json:"dismiss_stale_approvals"`
 | 
			
		||||
	RequireSignedCommits          bool     `json:"require_signed_commits"`
 | 
			
		||||
@@ -79,6 +81,7 @@ type EditBranchProtectionOption struct {
 | 
			
		||||
	ApprovalsWhitelistUsernames   []string `json:"approvals_whitelist_username"`
 | 
			
		||||
	ApprovalsWhitelistTeams       []string `json:"approvals_whitelist_teams"`
 | 
			
		||||
	BlockOnRejectedReviews        *bool    `json:"block_on_rejected_reviews"`
 | 
			
		||||
	BlockOnOfficialReviewRequests *bool    `json:"block_on_official_review_requests"`
 | 
			
		||||
	BlockOnOutdatedBranch         *bool    `json:"block_on_outdated_branch"`
 | 
			
		||||
	DismissStaleApprovals         *bool    `json:"dismiss_stale_approvals"`
 | 
			
		||||
	RequireSignedCommits          *bool    `json:"require_signed_commits"`
 | 
			
		||||
@@ -92,6 +95,9 @@ type ListBranchProtectionsOptions struct {
 | 
			
		||||
 | 
			
		||||
// ListBranchProtections list branch protections for a repo
 | 
			
		||||
func (c *Client) ListBranchProtections(owner, repo string, opt ListBranchProtectionsOptions) ([]*BranchProtection, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -104,6 +110,9 @@ func (c *Client) ListBranchProtections(owner, repo string, opt ListBranchProtect
 | 
			
		||||
 | 
			
		||||
// GetBranchProtection gets a branch protection
 | 
			
		||||
func (c *Client) GetBranchProtection(owner, repo, name string) (*BranchProtection, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -114,6 +123,9 @@ func (c *Client) GetBranchProtection(owner, repo, name string) (*BranchProtectio
 | 
			
		||||
 | 
			
		||||
// CreateBranchProtection creates a branch protection for a repo
 | 
			
		||||
func (c *Client) CreateBranchProtection(owner, repo string, opt CreateBranchProtectionOption) (*BranchProtection, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -128,6 +140,9 @@ func (c *Client) CreateBranchProtection(owner, repo string, opt CreateBranchProt
 | 
			
		||||
 | 
			
		||||
// EditBranchProtection edits a branch protection for a repo
 | 
			
		||||
func (c *Client) EditBranchProtection(owner, repo, name string, opt EditBranchProtectionOption) (*BranchProtection, *Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -142,6 +157,9 @@ func (c *Client) EditBranchProtection(owner, repo, name string, opt EditBranchPr
 | 
			
		||||
 | 
			
		||||
// DeleteBranchProtection deletes a branch protection for a repo
 | 
			
		||||
func (c *Client) DeleteBranchProtection(owner, repo, name string) (*Response, error) {
 | 
			
		||||
	if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user