Sfoglia il codice sorgente

refactor: unify error handling in routing layer

ᴜɴᴋɴᴡᴏɴ 4 anni fa
parent
commit
9e9ca66467
95 ha cambiato i file con 1410 aggiunte e 1389 eliminazioni
  1. 4 0
      conf/locale/locale_en-US.ini
  2. 6 6
      internal/assets/conf/conf_gen.go
  3. 7 8
      internal/auth/auth.go
  4. 1 2
      internal/cmd/hook.go
  5. 2 3
      internal/cmd/serv.go
  6. 3 3
      internal/cmd/web.go
  7. 18 28
      internal/context/api.go
  8. 13 13
      internal/context/auth.go
  9. 38 36
      internal/context/context.go
  10. 7 8
      internal/context/org.go
  11. 13 14
      internal/context/repo.go
  12. 1 2
      internal/context/user.go
  13. 2 4
      internal/db/access.go
  14. 9 10
      internal/db/action.go
  15. 22 2
      internal/db/attachment.go
  16. 22 3
      internal/db/comment.go
  17. 0 139
      internal/db/error.go
  18. 0 15
      internal/db/errors/issue.go
  19. 0 21
      internal/db/errors/org.go
  20. 3 42
      internal/db/errors/repo.go
  21. 3 15
      internal/db/errors/user.go
  22. 0 34
      internal/db/errors/webhook.go
  23. 29 9
      internal/db/issue.go
  24. 26 6
      internal/db/issue_label.go
  25. 8 8
      internal/db/login_source.go
  26. 21 1
      internal/db/milestone.go
  27. 22 2
      internal/db/org_team.go
  28. 33 9
      internal/db/pull.go
  29. 23 4
      internal/db/release.go
  30. 44 11
      internal/db/repo.go
  31. 22 3
      internal/db/repo_branch.go
  32. 22 2
      internal/db/ssh_key.go
  33. 28 8
      internal/db/user.go
  34. 1 1
      internal/db/user_mail.go
  35. 41 3
      internal/db/webhook.go
  36. 16 0
      internal/errutil/errutil.go
  37. 25 5
      internal/gitutil/error.go
  38. 27 0
      internal/osutil/error.go
  39. 2 2
      internal/route/admin/admin.go
  40. 8 8
      internal/route/admin/auths.go
  41. 8 6
      internal/route/admin/notice.go
  42. 7 7
      internal/route/admin/repos.go
  43. 17 17
      internal/route/admin/users.go
  44. 3 3
      internal/route/api/v1/admin/org.go
  45. 3 4
      internal/route/api/v1/admin/org_repo.go
  46. 9 9
      internal/route/api/v1/admin/org_team.go
  47. 4 4
      internal/route/api/v1/admin/repo.go
  48. 10 11
      internal/route/api/v1/admin/user.go
  49. 11 12
      internal/route/api/v1/api.go
  50. 1 8
      internal/route/api/v1/misc/markdown.go
  51. 11 11
      internal/route/api/v1/org/org.go
  52. 4 4
      internal/route/api/v1/org/team.go
  53. 8 13
      internal/route/api/v1/repo/branch.go
  54. 19 18
      internal/route/api/v1/repo/collaborators.go
  55. 9 10
      internal/route/api/v1/repo/commits.go
  56. 5 5
      internal/route/api/v1/repo/contents.go
  57. 5 5
      internal/route/api/v1/repo/file.go
  58. 24 27
      internal/route/api/v1/repo/hook.go
  59. 20 21
      internal/route/api/v1/repo/issue.go
  60. 11 11
      internal/route/api/v1/repo/issue_comment.go
  61. 15 16
      internal/route/api/v1/repo/issue_label.go
  62. 19 22
      internal/route/api/v1/repo/key.go
  63. 7 8
      internal/route/api/v1/repo/label.go
  64. 7 7
      internal/route/api/v1/repo/milestone.go
  65. 35 37
      internal/route/api/v1/repo/repo.go
  66. 3 3
      internal/route/api/v1/repo/tree.go
  67. 3 3
      internal/route/api/v1/user/app.go
  68. 8 7
      internal/route/api/v1/user/email.go
  69. 4 4
      internal/route/api/v1/user/follower.go
  70. 15 14
      internal/route/api/v1/user/key.go
  71. 1 2
      internal/route/api/v1/user/user.go
  72. 1 1
      internal/route/dev/template.go
  73. 7 7
      internal/route/home.go
  74. 10 11
      internal/route/org/members.go
  75. 6 7
      internal/route/org/org.go
  76. 14 15
      internal/route/org/setting.go
  77. 26 26
      internal/route/org/teams.go
  78. 5 5
      internal/route/repo/branch.go
  79. 11 11
      internal/route/repo/commit.go
  80. 2 2
      internal/route/repo/download.go
  81. 18 18
      internal/route/repo/editor.go
  82. 10 11
      internal/route/repo/http.go
  83. 79 100
      internal/route/repo/issue.go
  84. 42 42
      internal/route/repo/pull.go
  85. 21 29
      internal/route/repo/release.go
  86. 20 21
      internal/route/repo/repo.go
  87. 44 52
      internal/route/repo/setting.go
  88. 15 15
      internal/route/repo/view.go
  89. 62 58
      internal/route/repo/webhook.go
  90. 22 22
      internal/route/repo/wiki.go
  91. 34 34
      internal/route/user/auth.go
  92. 31 31
      internal/route/user/home.go
  93. 7 8
      internal/route/user/profile.go
  94. 44 44
      internal/route/user/setting.go
  95. 1 0
      internal/template/template.go

+ 4 - 0
conf/locale/locale_en-US.ini

@@ -43,6 +43,10 @@ issues = Issues
 
 cancel = Cancel
 
+[status]
+page_not_found = Page Not Found
+internal_server_error = Internal Server Error
+
 [install]
 install = Installation
 title = Install Steps For First-time Run

File diff suppressed because it is too large
+ 6 - 6
internal/assets/conf/conf_gen.go


+ 7 - 8
internal/auth/auth.go

@@ -15,7 +15,6 @@ import (
 
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
 	"gogs.io/gogs/internal/tool"
 )
 
@@ -70,8 +69,8 @@ func SignedInID(c *macaron.Context, sess session.Store) (_ int64, isTokenAuth bo
 	}
 	if id, ok := uid.(int64); ok {
 		if _, err := db.GetUserByID(id); err != nil {
-			if !errors.IsUserNotExist(err) {
-				log.Error("GetUserByID: %v", err)
+			if !db.IsErrUserNotExist(err) {
+				log.Error("Failed to get user by ID: %v", err)
 			}
 			return 0, false
 		}
@@ -95,8 +94,8 @@ func SignedInUser(ctx *macaron.Context, sess session.Store) (_ *db.User, isBasic
 			if len(webAuthUser) > 0 {
 				u, err := db.GetUserByName(webAuthUser)
 				if err != nil {
-					if !errors.IsUserNotExist(err) {
-						log.Error("GetUserByName: %v", err)
+					if !db.IsErrUserNotExist(err) {
+						log.Error("Failed to get user by name: %v", err)
 						return nil, false, false
 					}
 
@@ -110,7 +109,7 @@ func SignedInUser(ctx *macaron.Context, sess session.Store) (_ *db.User, isBasic
 						}
 						if err = db.CreateUser(u); err != nil {
 							// FIXME: should I create a system notice?
-							log.Error("CreateUser: %v", err)
+							log.Error("Failed to create user: %v", err)
 							return nil, false, false
 						} else {
 							return u, false, false
@@ -130,8 +129,8 @@ func SignedInUser(ctx *macaron.Context, sess session.Store) (_ *db.User, isBasic
 
 				u, err := db.UserLogin(uname, passwd, -1)
 				if err != nil {
-					if !errors.IsUserNotExist(err) {
-						log.Error("UserLogin: %v", err)
+					if !db.IsErrUserNotExist(err) {
+						log.Error("Failed to authenticate user: %v", err)
 					}
 					return nil, false, false
 				}

+ 1 - 2
internal/cmd/hook.go

@@ -23,7 +23,6 @@ import (
 
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
 	"gogs.io/gogs/internal/email"
 	"gogs.io/gogs/internal/httplib"
 )
@@ -93,7 +92,7 @@ func runHookPreReceive(c *cli.Context) error {
 		repoID := com.StrTo(os.Getenv(db.ENV_REPO_ID)).MustInt64()
 		protectBranch, err := db.GetProtectBranchOfRepoByName(repoID, branchName)
 		if err != nil {
-			if errors.IsErrBranchNotExist(err) {
+			if db.IsErrBranchNotExist(err) {
 				continue
 			}
 			fail("Internal error", "GetProtectBranchOfRepoByName [repo_id: %d, branch: %s]: %v", repoID, branchName, err)

+ 2 - 3
internal/cmd/serv.go

@@ -18,7 +18,6 @@ import (
 
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
 )
 
 const (
@@ -164,7 +163,7 @@ func runServ(c *cli.Context) error {
 
 	owner, err := db.GetUserByName(ownerName)
 	if err != nil {
-		if errors.IsUserNotExist(err) {
+		if db.IsErrUserNotExist(err) {
 			fail("Repository owner does not exist", "Unregistered owner: %s", ownerName)
 		}
 		fail("Internal error", "Failed to get repository owner '%s': %v", ownerName, err)
@@ -172,7 +171,7 @@ func runServ(c *cli.Context) error {
 
 	repo, err := db.GetRepositoryByName(owner.ID, repoName)
 	if err != nil {
-		if errors.IsRepoNotExist(err) {
+		if db.IsErrRepoNotExist(err) {
 			fail(_ACCESS_DENIED_MESSAGE, "Repository does not exist: %s/%s", owner.Name, repoName)
 		}
 		fail("Internal error", "Failed to get repository: %v", err)

+ 3 - 3
internal/cmd/web.go

@@ -318,7 +318,7 @@ func runWeb(c *cli.Context) error {
 		m.Get("/attachments/:uuid", func(c *context.Context) {
 			attach, err := db.GetAttachmentByUUID(c.Params(":uuid"))
 			if err != nil {
-				c.NotFoundOrServerError("GetAttachmentByUUID", db.IsErrAttachmentNotExist, err)
+				c.NotFoundOrError(err, "get attachment by UUID")
 				return
 			} else if !com.IsFile(attach.LocalPath()) {
 				c.NotFound()
@@ -327,7 +327,7 @@ func runWeb(c *cli.Context) error {
 
 			fr, err := os.Open(attach.LocalPath())
 			if err != nil {
-				c.ServerError("open attachment file", err)
+				c.Error(err, "open attachment file")
 				return
 			}
 			defer fr.Close()
@@ -336,7 +336,7 @@ func runWeb(c *cli.Context) error {
 			c.Header().Set("Content-Disposition", fmt.Sprintf(`inline; filename="%s"`, attach.Name))
 
 			if _, err = io.Copy(c.Resp, fr); err != nil {
-				c.ServerError("copy from file to response", err)
+				c.Error(err, "copy from file to response")
 				return
 			}
 		})

+ 18 - 28
internal/context/api.go

@@ -14,6 +14,7 @@ import (
 	log "unknwon.dev/clog/v2"
 
 	"gogs.io/gogs/internal/conf"
+	"gogs.io/gogs/internal/errutil"
 )
 
 type APIContext struct {
@@ -28,26 +29,6 @@ type APIContext struct {
 // FIXME: move this constant to github.com/gogs/go-gogs-client
 const DocURL = "https://github.com/gogs/docs-api"
 
-// Error responses error message to client with given message.
-// If status is 500, also it prints error to log.
-func (c *APIContext) Error(status int, title string, obj interface{}) {
-	var message string
-	if err, ok := obj.(error); ok {
-		message = err.Error()
-	} else {
-		message = obj.(string)
-	}
-
-	if status == http.StatusInternalServerError {
-		log.ErrorDepth(5, "%s: %s", title, message)
-	}
-
-	c.JSON(status, map[string]string{
-		"message": message,
-		"url":     DocURL,
-	})
-}
-
 // NoContent renders the 204 response.
 func (c *APIContext) NoContent() {
 	c.Status(http.StatusNoContent)
@@ -58,25 +39,34 @@ func (c *APIContext) NotFound() {
 	c.Status(http.StatusNotFound)
 }
 
-// ServerError renders the 500 response.
-func (c *APIContext) ServerError(title string, err error) {
-	c.Error(http.StatusInternalServerError, title, err)
+// ErrorStatus renders error with given status code.
+func (c *APIContext) ErrorStatus(status int, err error) {
+	c.JSON(status, map[string]string{
+		"message": err.Error(),
+		"url":     DocURL,
+	})
+}
+
+// Error renders the 500 response.
+func (c *APIContext) Error(err error, msg string) {
+	log.ErrorDepth(5, "%s: %v", msg, err)
+	c.ErrorStatus(http.StatusInternalServerError, err)
 }
 
 // Errorf renders the 500 response with formatted message.
 func (c *APIContext) Errorf(err error, format string, args ...interface{}) {
-	c.Error(http.StatusInternalServerError, fmt.Sprintf(format, args...), err)
+	c.Error(err, fmt.Sprintf(format, args...))
 }
 
-// NotFoundOrServerError use error check function to determine if the error
+// NotFoundOrError use error check function to determine if the error
 // is about not found. It responses with 404 status code for not found error,
 // or error context description for logging purpose of 500 server error.
-func (c *APIContext) NotFoundOrServerError(title string, errck func(error) bool, err error) {
-	if errck(err) {
+func (c *APIContext) NotFoundOrError(err error, msg string) {
+	if errutil.IsNotFound(err) {
 		c.NotFound()
 		return
 	}
-	c.ServerError(title, err)
+	c.Error(err, msg)
 }
 
 // SetLinkHeader sets pagination link header by given total number and page size.

+ 13 - 13
internal/context/auth.go

@@ -28,26 +28,26 @@ func Toggle(options *ToggleOptions) macaron.Handler {
 	return func(c *Context) {
 		// Cannot view any page before installation.
 		if !conf.Security.InstallLock {
-			c.Redirect(conf.Server.Subpath + "/install")
+			c.RedirectSubpath("/install")
 			return
 		}
 
 		// Check prohibit login users.
 		if c.IsLogged && c.User.ProhibitLogin {
 			c.Data["Title"] = c.Tr("auth.prohibit_login")
-			c.HTML(200, "user/auth/prohibit_login")
+			c.Success( "user/auth/prohibit_login")
 			return
 		}
 
 		// Check non-logged users landing page.
 		if !c.IsLogged && c.Req.RequestURI == "/" && conf.Server.LandingURL != "/" {
-			c.SubURLRedirect(conf.Server.LandingURL)
+			c.RedirectSubpath(conf.Server.LandingURL)
 			return
 		}
 
 		// Redirect to dashboard if user tries to visit any non-login page.
 		if options.SignOutRequired && c.IsLogged && c.Req.RequestURI != "/" {
-			c.Redirect(conf.Server.Subpath + "/")
+			c.RedirectSubpath("/")
 			return
 		}
 
@@ -62,18 +62,18 @@ func Toggle(options *ToggleOptions) macaron.Handler {
 			if !c.IsLogged {
 				// Restrict API calls with error message.
 				if auth.IsAPIPath(c.Req.URL.Path) {
-					c.JSON(403, map[string]string{
-						"message": "Only signed in user is allowed to call APIs.",
+					c.JSON(http.StatusForbidden, map[string]string{
+						"message": "Only authenticated user is allowed to call APIs.",
 					})
 					return
 				}
 
 				c.SetCookie("redirect_to", url.QueryEscape(conf.Server.Subpath+c.Req.RequestURI), 0, conf.Server.Subpath)
-				c.Redirect(conf.Server.Subpath + "/user/login")
+				c.RedirectSubpath("/user/login")
 				return
 			} else if !c.User.IsActive && conf.Auth.RequireEmailConfirmation {
-				c.Data["Title"] = c.Tr("auth.active_your_account")
-				c.HTML(200, "user/auth/activate")
+				c.Title("auth.active_your_account")
+				c.Success("user/auth/activate")
 				return
 			}
 		}
@@ -82,21 +82,21 @@ func Toggle(options *ToggleOptions) macaron.Handler {
 		if !options.SignOutRequired && !c.IsLogged && !auth.IsAPIPath(c.Req.URL.Path) &&
 			len(c.GetCookie(conf.Security.CookieUsername)) > 0 {
 			c.SetCookie("redirect_to", url.QueryEscape(conf.Server.Subpath+c.Req.RequestURI), 0, conf.Server.Subpath)
-			c.Redirect(conf.Server.Subpath + "/user/login")
+			c.RedirectSubpath("/user/login")
 			return
 		}
 
 		if options.AdminRequired {
 			if !c.User.IsAdmin {
-				c.Error(403)
+				c.Status(http.StatusForbidden)
 				return
 			}
-			c.Data["PageIsAdmin"] = true
+			c.PageIs("Admin")
 		}
 	}
 }
 
-// RequireBasicAuth verifies HTTP Basic Authentication header with given credentials
+// RequireBasicAuth verifies HTTP Basic Authentication header with given credentials.
 func (c *Context) RequireBasicAuth(username, password string) {
 	fields := strings.Fields(c.Req.Header.Get("Authorization"))
 	if len(fields) != 2 || fields[0] != "Basic" {

+ 38 - 36
internal/context/context.go

@@ -23,7 +23,7 @@ import (
 	"gogs.io/gogs/internal/auth"
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
+	"gogs.io/gogs/internal/errutil"
 	"gogs.io/gogs/internal/form"
 	"gogs.io/gogs/internal/template"
 )
@@ -149,15 +149,15 @@ func (c *Context) RawRedirect(location string, status ...int) {
 	c.Context.Redirect(location, status...)
 }
 
-// Redirect responses redirection wtih given location and status.
+// Redirect responses redirection with given location and status.
 // It escapes special characters in the location string.
 func (c *Context) Redirect(location string, status ...int) {
 	c.Context.Redirect(template.EscapePound(location), status...)
 }
 
-// SubURLRedirect responses redirection wtih given location and status.
+// RedirectSubpath responses redirection with given location and status.
 // It prepends setting.Server.Subpath to the location string.
-func (c *Context) SubURLRedirect(location string, status ...int) {
+func (c *Context) RedirectSubpath(location string, status ...int) {
 	c.Redirect(conf.Server.Subpath+location, status...)
 }
 
@@ -171,44 +171,46 @@ func (c *Context) RenderWithErr(msg, tpl string, f interface{}) {
 	c.HTML(http.StatusOK, tpl)
 }
 
-// Handle handles and logs error by given status.
-func (c *Context) Handle(status int, msg string, err error) {
-	switch status {
-	case http.StatusNotFound:
-		c.Data["Title"] = "Page Not Found"
-	case http.StatusInternalServerError:
-		c.Data["Title"] = "Internal Server Error"
-		log.ErrorDepth(5, "%s: %v", msg, err)
-		if !conf.IsProdMode() || (c.IsLogged && c.User.IsAdmin) {
-			c.Data["ErrorMsg"] = err
-		}
-	}
-	c.HTML(status, fmt.Sprintf("status/%d", status))
-}
-
 // NotFound renders the 404 page.
 func (c *Context) NotFound() {
-	c.Handle(http.StatusNotFound, "", nil)
+	c.Title("status.page_not_found")
+	c.HTML(http.StatusNotFound, fmt.Sprintf("status/%d", http.StatusNotFound))
 }
 
-// ServerError renders the 500 page.
-func (c *Context) ServerError(msg string, err error) {
-	c.Handle(http.StatusInternalServerError, msg, err)
+// Error renders the 500 page.
+func (c *Context) Error(err error, msg string) {
+	log.ErrorDepth(5, "%s: %v", msg, err)
+
+	c.Title("status.internal_server_error")
+
+	// Only in non-production mode or admin can see the actual error message.
+	if !conf.IsProdMode() || (c.IsLogged && c.User.IsAdmin) {
+		c.Data["ErrorMsg"] = err
+	}
+	c.HTML(http.StatusInternalServerError, fmt.Sprintf("status/%d", http.StatusInternalServerError))
+}
+
+// Errorf renders the 500 response with formatted message.
+func (c *Context) Errorf(err error, format string, args ...interface{}) {
+	c.Error(err, fmt.Sprintf(format, args...))
 }
 
-// NotFoundOrServerError use error check function to determine if the error
-// is about not found. It responses with 404 status code for not found error,
-// or error context description for logging purpose of 500 server error.
-func (c *Context) NotFoundOrServerError(msg string, errck func(error) bool, err error) {
-	if errck(err) {
+// NotFoundOrError responses with 404 page for not found error and 500 page otherwise.
+func (c *Context) NotFoundOrError(err error, msg string) {
+	if errutil.IsNotFound(err) {
 		c.NotFound()
 		return
 	}
-	c.ServerError(msg, err)
+	c.Error(err, msg)
+}
+
+// NotFoundOrErrorf is same as NotFoundOrError but with formatted message.
+func (c *Context) NotFoundOrErrorf(err error, format string, args ...interface{}) {
+	c.NotFoundOrError(err, fmt.Sprintf(format, args...))
 }
 
-func (c *Context) HandleText(status int, msg string) {
-	c.PlainText(status, []byte(msg))
+func (c *Context) PlainText(status int, msg string) {
+	c.Render.PlainText(status, []byte(msg))
 }
 
 func (c *Context) ServeContent(name string, r io.ReadSeeker, params ...interface{}) {
@@ -259,7 +261,7 @@ func Contexter() macaron.Handler {
 
 			owner, err := db.GetUserByName(ownerName)
 			if err != nil {
-				c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
+				c.NotFoundOrError(err, "get user by name")
 				return
 			}
 
@@ -273,7 +275,7 @@ func Contexter() macaron.Handler {
 			if !strings.HasPrefix(conf.Server.ExternalURL, "https://") {
 				insecureFlag = "--insecure "
 			}
-			c.PlainText(http.StatusOK, []byte(com.Expand(`<!doctype html>
+			c.PlainText(http.StatusOK, com.Expand(`<!doctype html>
 <html>
 	<head>
 		<meta name="go-import" content="{GoGetImport} git {CloneLink}">
@@ -284,12 +286,12 @@ func Contexter() macaron.Handler {
 	</body>
 </html>
 `, map[string]string{
-				"GoGetImport":    path.Join(conf.Server.URL.Host, conf.Server.Subpath, repo.FullName()),
+				"GoGetImport":    path.Join(conf.Server.URL.Host, conf.Server.Subpath, ownerName, repoName),
 				"CloneLink":      db.ComposeHTTPSCloneURL(ownerName, repoName),
 				"GoDocDirectory": prefix + "{/dir}",
 				"GoDocFile":      prefix + "{/dir}/{file}#L{line}",
 				"InsecureFlag":   insecureFlag,
-			})))
+			}))
 			return
 		}
 
@@ -318,7 +320,7 @@ func Contexter() macaron.Handler {
 		// If request sends files, parse them here otherwise the Query() can't be parsed and the CsrfToken will be invalid.
 		if c.Req.Method == "POST" && strings.Contains(c.Req.Header.Get("Content-Type"), "multipart/form-data") {
 			if err := c.Req.ParseMultipartForm(conf.Attachment.MaxSize << 20); err != nil && !strings.Contains(err.Error(), "EOF") { // 32MB max size
-				c.ServerError("ParseMultipartForm", err)
+				c.Error(err, "parse multipart form")
 				return
 			}
 		}

+ 7 - 8
internal/context/org.go

@@ -11,7 +11,6 @@ import (
 
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
 )
 
 type Organization struct {
@@ -50,7 +49,7 @@ func HandleOrgAssignment(c *Context, args ...bool) {
 	var err error
 	c.Org.Organization, err = db.GetUserByName(orgName)
 	if err != nil {
-		c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
+		c.NotFoundOrError(err, "get organization by name")
 		return
 	}
 	org := c.Org.Organization
@@ -85,7 +84,7 @@ func HandleOrgAssignment(c *Context, args ...bool) {
 	}
 	if (requireMember && !c.Org.IsMember) ||
 		(requireOwner && !c.Org.IsOwner) {
-		c.Handle(404, "OrgAssignment", err)
+		c.NotFound()
 		return
 	}
 	c.Data["IsOrganizationOwner"] = c.Org.IsOwner
@@ -98,13 +97,13 @@ func HandleOrgAssignment(c *Context, args ...bool) {
 	if c.Org.IsMember {
 		if c.Org.IsOwner {
 			if err := org.GetTeams(); err != nil {
-				c.Handle(500, "GetTeams", err)
+				c.Error(err, "get teams")
 				return
 			}
 		} else {
 			org.Teams, err = org.GetUserTeams(c.User.ID)
 			if err != nil {
-				c.Handle(500, "GetUserTeams", err)
+				c.Error(err, "get user teams")
 				return
 			}
 		}
@@ -124,20 +123,20 @@ func HandleOrgAssignment(c *Context, args ...bool) {
 		}
 
 		if !teamExists {
-			c.Handle(404, "OrgAssignment", err)
+			c.NotFound()
 			return
 		}
 
 		c.Data["IsTeamMember"] = c.Org.IsTeamMember
 		if requireTeamMember && !c.Org.IsTeamMember {
-			c.Handle(404, "OrgAssignment", err)
+			c.NotFound()
 			return
 		}
 
 		c.Org.IsTeamAdmin = c.Org.Team.IsOwnerTeam() || c.Org.Team.Authorize >= db.ACCESS_MODE_ADMIN
 		c.Data["IsTeamAdmin"] = c.Org.IsTeamAdmin
 		if requireTeamAdmin && !c.Org.IsTeamAdmin {
-			c.Handle(404, "OrgAssignment", err)
+			c.NotFound()
 			return
 		}
 	}

+ 13 - 14
internal/context/repo.go

@@ -18,7 +18,6 @@ import (
 
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/db"
-	dberrors "gogs.io/gogs/internal/db/errors"
 )
 
 type PullRequest struct {
@@ -147,7 +146,7 @@ func RepoAssignment(pages ...bool) macaron.Handler {
 		} else {
 			owner, err = db.GetUserByName(ownerName)
 			if err != nil {
-				c.NotFoundOrServerError("GetUserByName", dberrors.IsUserNotExist, err)
+				c.NotFoundOrError(err, "get user by name")
 				return
 			}
 		}
@@ -156,7 +155,7 @@ func RepoAssignment(pages ...bool) macaron.Handler {
 
 		repo, err := db.GetRepositoryByName(owner.ID, repoName)
 		if err != nil {
-			c.NotFoundOrServerError("GetRepositoryByName", dberrors.IsRepoNotExist, err)
+			c.NotFoundOrError(err, "get repository by name")
 			return
 		}
 
@@ -173,7 +172,7 @@ func RepoAssignment(pages ...bool) macaron.Handler {
 		} else {
 			mode, err := db.UserAccessMode(c.UserID(), repo)
 			if err != nil {
-				c.ServerError("UserAccessMode", err)
+				c.Error(err, "get user access mode")
 				return
 			}
 			c.Repo.AccessMode = mode
@@ -212,7 +211,7 @@ func RepoAssignment(pages ...bool) macaron.Handler {
 		if repo.IsMirror {
 			c.Repo.Mirror, err = db.GetMirrorByRepoID(repo.ID)
 			if err != nil {
-				c.ServerError("GetMirror", err)
+				c.Error(err, "get mirror by repository ID")
 				return
 			}
 			c.Data["MirrorEnablePrune"] = c.Repo.Mirror.EnablePrune
@@ -222,14 +221,14 @@ func RepoAssignment(pages ...bool) macaron.Handler {
 
 		gitRepo, err := git.Open(db.RepoPath(ownerName, repoName))
 		if err != nil {
-			c.ServerError("open repository", err)
+			c.Error(err, "open repository")
 			return
 		}
 		c.Repo.GitRepo = gitRepo
 
 		tags, err := c.Repo.GitRepo.Tags()
 		if err != nil {
-			c.ServerError("get tags", err)
+			c.Error(err, "get tags")
 			return
 		}
 		c.Data["Tags"] = tags
@@ -260,7 +259,7 @@ func RepoAssignment(pages ...bool) macaron.Handler {
 		c.Data["TagName"] = c.Repo.TagName
 		branches, err := c.Repo.GitRepo.Branches()
 		if err != nil {
-			c.ServerError("get branches", err)
+			c.Error(err, "get branches")
 			return
 		}
 		c.Data["Branches"] = branches
@@ -300,7 +299,7 @@ func RepoRef() macaron.Handler {
 			repoPath := db.RepoPath(c.Repo.Owner.Name, c.Repo.Repository.Name)
 			c.Repo.GitRepo, err = git.Open(repoPath)
 			if err != nil {
-				c.Handle(500, "RepoRef Invalid repo "+repoPath, err)
+				c.Error(err, "open repository")
 				return
 			}
 		}
@@ -311,14 +310,14 @@ func RepoRef() macaron.Handler {
 			if !c.Repo.GitRepo.HasBranch(refName) {
 				branches, err := c.Repo.GitRepo.Branches()
 				if err != nil {
-					c.ServerError("get branches", err)
+					c.Error(err, "get branches")
 					return
 				}
 				refName = branches[0]
 			}
 			c.Repo.Commit, err = c.Repo.GitRepo.BranchCommit(refName)
 			if err != nil {
-				c.ServerError("get branch commit", err)
+				c.Error(err, "get branch commit")
 				return
 			}
 			c.Repo.CommitID = c.Repo.Commit.ID.String()
@@ -349,7 +348,7 @@ func RepoRef() macaron.Handler {
 
 				c.Repo.Commit, err = c.Repo.GitRepo.BranchCommit(refName)
 				if err != nil {
-					c.ServerError("get branch commit", err)
+					c.Error(err, "get branch commit")
 					return
 				}
 				c.Repo.CommitID = c.Repo.Commit.ID.String()
@@ -358,7 +357,7 @@ func RepoRef() macaron.Handler {
 				c.Repo.IsViewTag = true
 				c.Repo.Commit, err = c.Repo.GitRepo.TagCommit(refName)
 				if err != nil {
-					c.ServerError("get tag commit", err)
+					c.Error(err, "get tag commit")
 					return
 				}
 				c.Repo.CommitID = c.Repo.Commit.ID.String()
@@ -372,7 +371,7 @@ func RepoRef() macaron.Handler {
 					return
 				}
 			} else {
-				c.Handle(404, "RepoRef invalid repo", fmt.Errorf("branch or tag not exist: %s", refName))
+				c.NotFound()
 				return
 			}
 		}

+ 1 - 2
internal/context/user.go

@@ -8,7 +8,6 @@ import (
 	"gopkg.in/macaron.v1"
 
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
 )
 
 // ParamsUser is the wrapper type of the target user defined by URL parameter, namely ':username'.
@@ -22,7 +21,7 @@ func InjectParamsUser() macaron.Handler {
 	return func(c *Context) {
 		user, err := db.GetUserByName(c.Params(":username"))
 		if err != nil {
-			c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
+			c.NotFoundOrError(err, "get user by name")
 			return
 		}
 		c.Map(&ParamsUser{user})

+ 2 - 4
internal/db/access.go

@@ -8,8 +8,6 @@ import (
 	"fmt"
 
 	log "unknwon.dev/clog/v2"
-
-	"gogs.io/gogs/internal/db/errors"
 )
 
 type AccessMode int
@@ -110,8 +108,8 @@ func (u *User) GetRepositoryAccesses() (map[*Repository]AccessMode, error) {
 	for _, access := range accesses {
 		repo, err := GetRepositoryByID(access.RepoID)
 		if err != nil {
-			if errors.IsRepoNotExist(err) {
-				log.Error("GetRepositoryByID: %v", err)
+			if IsErrRepoNotExist(err) {
+				log.Error("Failed to get repository by ID: %v", err)
 				continue
 			}
 			return nil, err

+ 9 - 10
internal/db/action.go

@@ -20,7 +20,6 @@ import (
 	api "github.com/gogs/go-gogs-client"
 
 	"gogs.io/gogs/internal/conf"
-	"gogs.io/gogs/internal/db/errors"
 	"gogs.io/gogs/internal/lazyregexp"
 	"gogs.io/gogs/internal/tool"
 )
@@ -256,16 +255,16 @@ func (pc *PushCommits) ToApiPayloadCommits(repoPath, repoURL string) ([]*api.Pay
 		author, err := GetUserByEmail(commit.AuthorEmail)
 		if err == nil {
 			authorUsername = author.Name
-		} else if !errors.IsUserNotExist(err) {
-			return nil, fmt.Errorf("GetUserByEmail: %v", err)
+		} else if !IsErrUserNotExist(err) {
+			return nil, fmt.Errorf("get user by email: %v", err)
 		}
 
 		committerUsername := ""
 		committer, err := GetUserByEmail(commit.CommitterEmail)
 		if err == nil {
 			committerUsername = committer.Name
-		} else if !errors.IsUserNotExist(err) {
-			return nil, fmt.Errorf("GetUserByEmail: %v", err)
+		} else if !IsErrUserNotExist(err) {
+			return nil, fmt.Errorf("get user by email: %v", err)
 		}
 
 		nameStatus, err := git.RepoShowNameStatus(repoPath, commit.Sha1)
@@ -304,8 +303,8 @@ func (pcs *PushCommits) AvatarLink(email string) string {
 		u, err := GetUserByEmail(email)
 		if err != nil {
 			pcs.avatars[email] = tool.AvatarLink(email)
-			if !errors.IsUserNotExist(err) {
-				log.Error("GetUserByEmail: %v", err)
+			if !IsErrUserNotExist(err) {
+				log.Error("get user by email: %v", err)
 			}
 		} else {
 			pcs.avatars[email] = u.RelAvatarLink()
@@ -341,7 +340,7 @@ func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit) err
 
 			issue, err := GetIssueByRef(ref)
 			if err != nil {
-				if errors.IsIssueNotExist(err) {
+				if IsErrIssueNotExist(err) {
 					continue
 				}
 				return err
@@ -383,7 +382,7 @@ func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit) err
 
 			issue, err := GetIssueByRef(ref)
 			if err != nil {
-				if errors.IsIssueNotExist(err) {
+				if IsErrIssueNotExist(err) {
 					continue
 				}
 				return err
@@ -423,7 +422,7 @@ func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit) err
 
 			issue, err := GetIssueByRef(ref)
 			if err != nil {
-				if errors.IsIssueNotExist(err) {
+				if IsErrIssueNotExist(err) {
 					continue
 				}
 				return err

+ 22 - 2
internal/db/attachment.go

@@ -16,6 +16,7 @@ import (
 	"xorm.io/xorm"
 
 	"gogs.io/gogs/internal/conf"
+	"gogs.io/gogs/internal/errutil"
 )
 
 // Attachment represent a attachment of issue/comment/release.
@@ -83,13 +84,32 @@ func NewAttachment(name string, buf []byte, file multipart.File) (_ *Attachment,
 	return attach, nil
 }
 
+var _ errutil.NotFound = (*ErrAttachmentNotExist)(nil)
+
+type ErrAttachmentNotExist struct {
+	args map[string]interface{}
+}
+
+func IsErrAttachmentNotExist(err error) bool {
+	_, ok := err.(ErrAttachmentNotExist)
+	return ok
+}
+
+func (err ErrAttachmentNotExist) Error() string {
+	return fmt.Sprintf("attachment does not exist: %v", err.args)
+}
+
+func (ErrAttachmentNotExist) NotFound() bool {
+	return true
+}
+
 func getAttachmentByUUID(e Engine, uuid string) (*Attachment, error) {
 	attach := &Attachment{UUID: uuid}
-	has, err := x.Get(attach)
+	has, err := e.Get(attach)
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, ErrAttachmentNotExist{0, uuid}
+		return nil, ErrAttachmentNotExist{args: map[string]interface{}{"uuid": uuid}}
 	}
 	return attach, nil
 }

+ 22 - 3
internal/db/comment.go

@@ -15,7 +15,7 @@ import (
 
 	api "github.com/gogs/go-gogs-client"
 
-	"gogs.io/gogs/internal/db/errors"
+	"gogs.io/gogs/internal/errutil"
 	"gogs.io/gogs/internal/markup"
 )
 
@@ -96,7 +96,7 @@ func (c *Comment) loadAttributes(e Engine) (err error) {
 	if c.Poster == nil {
 		c.Poster, err = GetUserByID(c.PosterID)
 		if err != nil {
-			if errors.IsUserNotExist(err) {
+			if IsErrUserNotExist(err) {
 				c.PosterID = -1
 				c.Poster = NewGhostUser()
 			} else {
@@ -391,6 +391,25 @@ func CreateRefComment(doer *User, repo *Repository, issue *Issue, content, commi
 	return err
 }
 
+var _ errutil.NotFound = (*ErrCommentNotExist)(nil)
+
+type ErrCommentNotExist struct {
+	args map[string]interface{}
+}
+
+func IsErrCommentNotExist(err error) bool {
+	_, ok := err.(ErrCommentNotExist)
+	return ok
+}
+
+func (err ErrCommentNotExist) Error() string {
+	return fmt.Sprintf("comment does not exist: %v", err.args)
+}
+
+func (ErrCommentNotExist) NotFound() bool {
+	return true
+}
+
 // GetCommentByID returns the comment by given ID.
 func GetCommentByID(id int64) (*Comment, error) {
 	c := new(Comment)
@@ -398,7 +417,7 @@ func GetCommentByID(id int64) (*Comment, error) {
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, ErrCommentNotExist{id, 0}
+		return nil, ErrCommentNotExist{args: map[string]interface{}{"commentID": id}}
 	}
 	return c, c.LoadAttributes()
 }

+ 0 - 139
internal/db/error.go

@@ -190,21 +190,6 @@ func (err ErrKeyAccessDenied) Error() string {
 		err.UserID, err.KeyID, err.Note)
 }
 
-type ErrDeployKeyNotExist struct {
-	ID     int64
-	KeyID  int64
-	RepoID int64
-}
-
-func IsErrDeployKeyNotExist(err error) bool {
-	_, ok := err.(ErrDeployKeyNotExist)
-	return ok
-}
-
-func (err ErrDeployKeyNotExist) Error() string {
-	return fmt.Sprintf("Deploy key does not exist [id: %d, key_id: %d, repo_id: %d]", err.ID, err.KeyID, err.RepoID)
-}
-
 type ErrDeployKeyAlreadyExist struct {
 	KeyID  int64
 	RepoID int64
@@ -348,20 +333,6 @@ func (err ErrReleaseAlreadyExist) Error() string {
 	return fmt.Sprintf("release tag already exist [tag_name: %s]", err.TagName)
 }
 
-type ErrReleaseNotExist struct {
-	ID      int64
-	TagName string
-}
-
-func IsErrReleaseNotExist(err error) bool {
-	_, ok := err.(ErrReleaseNotExist)
-	return ok
-}
-
-func (err ErrReleaseNotExist) Error() string {
-	return fmt.Sprintf("release tag does not exist [id: %d, tag_name: %s]", err.ID, err.TagName)
-}
-
 type ErrInvalidTagName struct {
 	TagName string
 }
@@ -388,116 +359,6 @@ func (err ErrRepoFileAlreadyExist) Error() string {
 	return fmt.Sprintf("repository file already exists [file_name: %s]", err.FileName)
 }
 
-// __________      .__  .__ __________                                     __
-// \______   \__ __|  | |  |\______   \ ____  ________ __   ____   _______/  |_
-//  |     ___/  |  \  | |  | |       _// __ \/ ____/  |  \_/ __ \ /  ___/\   __\
-//  |    |   |  |  /  |_|  |_|    |   \  ___< <_|  |  |  /\  ___/ \___ \  |  |
-//  |____|   |____/|____/____/____|_  /\___  >__   |____/  \___  >____  > |__|
-//                                  \/     \/   |__|           \/     \/
-
-type ErrPullRequestNotExist struct {
-	ID         int64
-	IssueID    int64
-	HeadRepoID int64
-	BaseRepoID int64
-	HeadBarcnh string
-	BaseBranch string
-}
-
-func IsErrPullRequestNotExist(err error) bool {
-	_, ok := err.(ErrPullRequestNotExist)
-	return ok
-}
-
-func (err ErrPullRequestNotExist) Error() string {
-	return fmt.Sprintf("pull request does not exist [id: %d, issue_id: %d, head_repo_id: %d, base_repo_id: %d, head_branch: %s, base_branch: %s]",
-		err.ID, err.IssueID, err.HeadRepoID, err.BaseRepoID, err.HeadBarcnh, err.BaseBranch)
-}
-
-// _________                                       __
-// \_   ___ \  ____   _____   _____   ____   _____/  |_
-// /    \  \/ /  _ \ /     \ /     \_/ __ \ /    \   __\
-// \     \___(  <_> )  Y Y  \  Y Y  \  ___/|   |  \  |
-//  \______  /\____/|__|_|  /__|_|  /\___  >___|  /__|
-//         \/             \/      \/     \/     \/
-
-type ErrCommentNotExist struct {
-	ID      int64
-	IssueID int64
-}
-
-func IsErrCommentNotExist(err error) bool {
-	_, ok := err.(ErrCommentNotExist)
-	return ok
-}
-
-func (err ErrCommentNotExist) Error() string {
-	return fmt.Sprintf("comment does not exist [id: %d, issue_id: %d]", err.ID, err.IssueID)
-}
-
-// .____          ___.          .__
-// |    |   _____ \_ |__   ____ |  |
-// |    |   \__  \ | __ \_/ __ \|  |
-// |    |___ / __ \| \_\ \  ___/|  |__
-// |_______ (____  /___  /\___  >____/
-//         \/    \/    \/     \/
-
-type ErrLabelNotExist struct {
-	LabelID int64
-	RepoID  int64
-}
-
-func IsErrLabelNotExist(err error) bool {
-	_, ok := err.(ErrLabelNotExist)
-	return ok
-}
-
-func (err ErrLabelNotExist) Error() string {
-	return fmt.Sprintf("label does not exist [label_id: %d, repo_id: %d]", err.LabelID, err.RepoID)
-}
-
-//    _____  .__.__                   __
-//   /     \ |__|  |   ____   _______/  |_  ____   ____   ____
-//  /  \ /  \|  |  | _/ __ \ /  ___/\   __\/  _ \ /    \_/ __ \
-// /    Y    \  |  |_\  ___/ \___ \  |  | (  <_> )   |  \  ___/
-// \____|__  /__|____/\___  >____  > |__|  \____/|___|  /\___  >
-//         \/             \/     \/                   \/     \/
-
-type ErrMilestoneNotExist struct {
-	ID     int64
-	RepoID int64
-}
-
-func IsErrMilestoneNotExist(err error) bool {
-	_, ok := err.(ErrMilestoneNotExist)
-	return ok
-}
-
-func (err ErrMilestoneNotExist) Error() string {
-	return fmt.Sprintf("milestone does not exist [id: %d, repo_id: %d]", err.ID, err.RepoID)
-}
-
-//    _____   __    __                .__                           __
-//   /  _  \_/  |__/  |______    ____ |  |__   _____   ____   _____/  |_
-//  /  /_\  \   __\   __\__  \ _/ ___\|  |  \ /     \_/ __ \ /    \   __\
-// /    |    \  |  |  |  / __ \\  \___|   Y  \  Y Y  \  ___/|   |  \  |
-// \____|__  /__|  |__| (____  /\___  >___|  /__|_|  /\___  >___|  /__|
-//         \/                \/     \/     \/      \/     \/     \/
-
-type ErrAttachmentNotExist struct {
-	ID   int64
-	UUID string
-}
-
-func IsErrAttachmentNotExist(err error) bool {
-	_, ok := err.(ErrAttachmentNotExist)
-	return ok
-}
-
-func (err ErrAttachmentNotExist) Error() string {
-	return fmt.Sprintf("attachment does not exist [id: %d, uuid: %s]", err.ID, err.UUID)
-}
-
 // .____                 .__           _________
 // |    |    ____   ____ |__| ____    /   _____/ ____  __ _________   ____  ____
 // |    |   /  _ \ / ___\|  |/    \   \_____  \ /  _ \|  |  \_  __ \_/ ___\/ __ \

+ 0 - 15
internal/db/errors/issue.go

@@ -6,21 +6,6 @@ package errors
 
 import "fmt"
 
-type IssueNotExist struct {
-	ID     int64
-	RepoID int64
-	Index  int64
-}
-
-func IsIssueNotExist(err error) bool {
-	_, ok := err.(IssueNotExist)
-	return ok
-}
-
-func (err IssueNotExist) Error() string {
-	return fmt.Sprintf("issue does not exist [id: %d, repo_id: %d, index: %d]", err.ID, err.RepoID, err.Index)
-}
-
 type InvalidIssueReference struct {
 	Ref string
 }

+ 0 - 21
internal/db/errors/org.go

@@ -1,21 +0,0 @@
-// Copyright 2018 The Gogs Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package errors
-
-import "fmt"
-
-type TeamNotExist struct {
-	TeamID int64
-	Name   string
-}
-
-func IsTeamNotExist(err error) bool {
-	_, ok := err.(TeamNotExist)
-	return ok
-}
-
-func (err TeamNotExist) Error() string {
-	return fmt.Sprintf("team does not exist [team_id: %d, name: %s]", err.TeamID, err.Name)
-}

+ 3 - 42
internal/db/errors/repo.go

@@ -4,35 +4,9 @@
 
 package errors
 
-import "fmt"
-
-type RepoNotExist struct {
-	ID     int64
-	UserID int64
-	Name   string
-}
-
-func IsRepoNotExist(err error) bool {
-	_, ok := err.(RepoNotExist)
-	return ok
-}
-
-func (err RepoNotExist) Error() string {
-	return fmt.Sprintf("repository does not exist [id: %d, user_id: %d, name: %s]", err.ID, err.UserID, err.Name)
-}
-
-type ReachLimitOfRepo struct {
-	Limit int
-}
-
-func IsReachLimitOfRepo(err error) bool {
-	_, ok := err.(ReachLimitOfRepo)
-	return ok
-}
-
-func (err ReachLimitOfRepo) Error() string {
-	return fmt.Sprintf("user has reached maximum limit of repositories [limit: %d]", err.Limit)
-}
+import (
+	"fmt"
+)
 
 type InvalidRepoReference struct {
 	Ref string
@@ -72,16 +46,3 @@ func IsBranchAlreadyExists(err error) bool {
 func (err BranchAlreadyExists) Error() string {
 	return fmt.Sprintf("branch already exists [name: %s]", err.Name)
 }
-
-type ErrBranchNotExist struct {
-	Name string
-}
-
-func IsErrBranchNotExist(err error) bool {
-	_, ok := err.(ErrBranchNotExist)
-	return ok
-}
-
-func (err ErrBranchNotExist) Error() string {
-	return fmt.Sprintf("branch does not exist [name: %s]", err.Name)
-}

+ 3 - 15
internal/db/errors/user.go

@@ -4,7 +4,9 @@
 
 package errors
 
-import "fmt"
+import (
+	"fmt"
+)
 
 type EmptyName struct{}
 
@@ -17,20 +19,6 @@ func (err EmptyName) Error() string {
 	return "empty name"
 }
 
-type UserNotExist struct {
-	UserID int64
-	Name   string
-}
-
-func IsUserNotExist(err error) bool {
-	_, ok := err.(UserNotExist)
-	return ok
-}
-
-func (err UserNotExist) Error() string {
-	return fmt.Sprintf("user does not exist [user_id: %d, name: %s]", err.UserID, err.Name)
-}
-
 type UserNotKeyOwner struct {
 	KeyID int64
 }

+ 0 - 34
internal/db/errors/webhook.go

@@ -1,34 +0,0 @@
-// Copyright 2017 The Gogs Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package errors
-
-import "fmt"
-
-type WebhookNotExist struct {
-	ID int64
-}
-
-func IsWebhookNotExist(err error) bool {
-	_, ok := err.(WebhookNotExist)
-	return ok
-}
-
-func (err WebhookNotExist) Error() string {
-	return fmt.Sprintf("webhook does not exist [id: %d]", err.ID)
-}
-
-type HookTaskNotExist struct {
-	HookID int64
-	UUID   string
-}
-
-func IsHookTaskNotExist(err error) bool {
-	_, ok := err.(HookTaskNotExist)
-	return ok
-}
-
-func (err HookTaskNotExist) Error() string {
-	return fmt.Sprintf("hook task does not exist [hook_id: %d, uuid: %s]", err.HookID, err.UUID)
-}

+ 29 - 9
internal/db/issue.go

@@ -17,6 +17,7 @@ import (
 
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/db/errors"
+	"gogs.io/gogs/internal/errutil"
 	"gogs.io/gogs/internal/tool"
 )
 
@@ -90,7 +91,7 @@ func (issue *Issue) loadAttributes(e Engine) (err error) {
 	if issue.Poster == nil {
 		issue.Poster, err = getUserByID(e, issue.PosterID)
 		if err != nil {
-			if errors.IsUserNotExist(err) {
+			if IsErrUserNotExist(err) {
 				issue.PosterID = -1
 				issue.Poster = NewGhostUser()
 			} else {
@@ -395,7 +396,7 @@ func (issue *Issue) GetAssignee() (err error) {
 	}
 
 	issue.Assignee, err = GetUserByID(issue.AssigneeID)
-	if errors.IsUserNotExist(err) {
+	if IsErrUserNotExist(err) {
 		return nil
 	}
 	return err
@@ -600,8 +601,8 @@ func (issue *Issue) ChangeAssignee(doer *User, assigneeID int64) (err error) {
 	}
 
 	issue.Assignee, err = GetUserByID(issue.AssigneeID)
-	if err != nil && !errors.IsUserNotExist(err) {
-		log.Error("GetUserByID [assignee_id: %v]: %v", issue.AssigneeID, err)
+	if err != nil && !IsErrUserNotExist(err) {
+		log.Error("Failed to get user by ID: %v", err)
 		return nil
 	}
 
@@ -673,8 +674,8 @@ func newIssue(e *xorm.Session, opts NewIssueOptions) (err error) {
 
 	if opts.Issue.AssigneeID > 0 {
 		assignee, err := getUserByID(e, opts.Issue.AssigneeID)
-		if err != nil && !errors.IsUserNotExist(err) {
-			return fmt.Errorf("getUserByID: %v", err)
+		if err != nil && !IsErrUserNotExist(err) {
+			return fmt.Errorf("get user by ID: %v", err)
 		}
 
 		// Assume assignee is invalid and drop silently.
@@ -796,6 +797,25 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string)
 	return nil
 }
 
+var _ errutil.NotFound = (*ErrIssueNotExist)(nil)
+
+type ErrIssueNotExist struct {
+	args map[string]interface{}
+}
+
+func IsErrIssueNotExist(err error) bool {
+	_, ok := err.(ErrIssueNotExist)
+	return ok
+}
+
+func (err ErrIssueNotExist) Error() string {
+	return fmt.Sprintf("issue does not exist: %v", err.args)
+}
+
+func (ErrIssueNotExist) NotFound() bool {
+	return true
+}
+
 // GetIssueByRef returns an Issue specified by a GFM reference.
 // See https://help.github.com/articles/writing-on-github#references for more information on the syntax.
 func GetIssueByRef(ref string) (*Issue, error) {
@@ -806,7 +826,7 @@ func GetIssueByRef(ref string) (*Issue, error) {
 
 	index := com.StrTo(ref[n+1:]).MustInt64()
 	if index == 0 {
-		return nil, errors.IssueNotExist{}
+		return nil, ErrIssueNotExist{args: map[string]interface{}{"ref": ref}}
 	}
 
 	repo, err := GetRepositoryByRef(ref[:n])
@@ -832,7 +852,7 @@ func GetRawIssueByIndex(repoID, index int64) (*Issue, error) {
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, errors.IssueNotExist{RepoID: repoID, Index: index}
+		return nil, ErrIssueNotExist{args: map[string]interface{}{"repoID": repoID, "index": index}}
 	}
 	return issue, nil
 }
@@ -852,7 +872,7 @@ func getRawIssueByID(e Engine, id int64) (*Issue, error) {
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, errors.IssueNotExist{ID: id}
+		return nil, ErrIssueNotExist{args: map[string]interface{}{"issueID": id}}
 	}
 	return issue, nil
 }

+ 26 - 6
internal/db/issue_label.go

@@ -14,6 +14,7 @@ import (
 
 	api "github.com/gogs/go-gogs-client"
 
+	"gogs.io/gogs/internal/errutil"
 	"gogs.io/gogs/internal/lazyregexp"
 	"gogs.io/gogs/internal/tool"
 )
@@ -103,23 +104,42 @@ func NewLabels(labels ...*Label) error {
 	return err
 }
 
+var _ errutil.NotFound = (*ErrLabelNotExist)(nil)
+
+type ErrLabelNotExist struct {
+	args map[string]interface{}
+}
+
+func IsErrLabelNotExist(err error) bool {
+	_, ok := err.(ErrLabelNotExist)
+	return ok
+}
+
+func (err ErrLabelNotExist) Error() string {
+	return fmt.Sprintf("label does not exist: %v", err.args)
+}
+
+func (ErrLabelNotExist) NotFound() bool {
+	return true
+}
+
 // getLabelOfRepoByName returns a label by Name in given repository.
 // If pass repoID as 0, then ORM will ignore limitation of repository
 // and can return arbitrary label with any valid ID.
 func getLabelOfRepoByName(e Engine, repoID int64, labelName string) (*Label, error) {
 	if len(labelName) <= 0 {
-		return nil, ErrLabelNotExist{0, repoID}
+		return nil, ErrLabelNotExist{args: map[string]interface{}{"repoID": repoID}}
 	}
 
 	l := &Label{
 		Name:   labelName,
 		RepoID: repoID,
 	}
-	has, err := x.Get(l)
+	has, err := e.Get(l)
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, ErrLabelNotExist{0, l.RepoID}
+		return nil, ErrLabelNotExist{args: map[string]interface{}{"repoID": repoID}}
 	}
 	return l, nil
 }
@@ -129,18 +149,18 @@ func getLabelOfRepoByName(e Engine, repoID int64, labelName string) (*Label, err
 // and can return arbitrary label with any valid ID.
 func getLabelOfRepoByID(e Engine, repoID, labelID int64) (*Label, error) {
 	if labelID <= 0 {
-		return nil, ErrLabelNotExist{labelID, repoID}
+		return nil, ErrLabelNotExist{args: map[string]interface{}{"repoID": repoID, "labelID": labelID}}
 	}
 
 	l := &Label{
 		ID:     labelID,
 		RepoID: repoID,
 	}
-	has, err := x.Get(l)
+	has, err := e.Get(l)
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, ErrLabelNotExist{l.ID, l.RepoID}
+		return nil, ErrLabelNotExist{args: map[string]interface{}{"repoID": repoID, "labelID": labelID}}
 	}
 	return l, nil
 }

+ 8 - 8
internal/db/login_source.go

@@ -556,7 +556,7 @@ func LoginViaLDAP(user *User, login, password string, source *LoginSource, autoR
 	username, fn, sn, mail, isAdmin, succeed := source.Cfg.(*LDAPConfig).SearchEntry(login, password, source.Type == LOGIN_DLDAP)
 	if !succeed {
 		// User not in LDAP, do nothing
-		return nil, errors.UserNotExist{Name: login}
+		return nil, ErrUserNotExist{args: map[string]interface{}{"login": login}}
 	}
 
 	if !autoRegister {
@@ -674,9 +674,9 @@ func LoginViaSMTP(user *User, login, password string, sourceID int64, cfg *SMTPC
 	if len(cfg.AllowedDomains) > 0 {
 		idx := strings.Index(login, "@")
 		if idx == -1 {
-			return nil, errors.UserNotExist{Name: login}
+			return nil, ErrUserNotExist{args: map[string]interface{}{"login": login}}
 		} else if !com.IsSliceContainsStr(strings.Split(cfg.AllowedDomains, ","), login[idx+1:]) {
-			return nil, errors.UserNotExist{Name: login}
+			return nil, ErrUserNotExist{args: map[string]interface{}{"login": login}}
 		}
 	}
 
@@ -695,7 +695,7 @@ func LoginViaSMTP(user *User, login, password string, sourceID int64, cfg *SMTPC
 		tperr, ok := err.(*textproto.Error)
 		if (ok && tperr.Code == 535) ||
 			strings.Contains(err.Error(), "Username and Password not accepted") {
-			return nil, errors.UserNotExist{Name: login}
+			return nil, ErrUserNotExist{args: map[string]interface{}{"login": login}}
 		}
 		return nil, err
 	}
@@ -735,7 +735,7 @@ func LoginViaSMTP(user *User, login, password string, sourceID int64, cfg *SMTPC
 func LoginViaPAM(user *User, login, password string, sourceID int64, cfg *PAMConfig, autoRegister bool) (*User, error) {
 	if err := pam.PAMAuth(cfg.ServiceName, login, password); err != nil {
 		if strings.Contains(err.Error(), "Authentication failure") {
-			return nil, errors.UserNotExist{Name: login}
+			return nil, ErrUserNotExist{args: map[string]interface{}{"login": login}}
 		}
 		return nil, err
 	}
@@ -768,7 +768,7 @@ func LoginViaGitHub(user *User, login, password string, sourceID int64, cfg *Git
 	fullname, email, url, location, err := github.Authenticate(cfg.APIEndpoint, login, password)
 	if err != nil {
 		if strings.Contains(err.Error(), "401") {
-			return nil, errors.UserNotExist{Name: login}
+			return nil, ErrUserNotExist{args: map[string]interface{}{"login": login}}
 		}
 		return nil, err
 	}
@@ -840,7 +840,7 @@ func UserLogin(username, password string, loginSourceID int64) (*User, error) {
 				return user, nil
 			}
 
-			return nil, errors.UserNotExist{UserID: user.ID, Name: user.Name}
+			return nil, ErrUserNotExist{args: map[string]interface{}{"userID": user.ID, "name": user.Name}}
 		}
 
 		// Remote login to the login source the user is associated with
@@ -854,7 +854,7 @@ func UserLogin(username, password string, loginSourceID int64) (*User, error) {
 
 	// Non-local login source is always greater than 0
 	if loginSourceID <= 0 {
-		return nil, errors.UserNotExist{UserID: -1, Name: username}
+		return nil, ErrUserNotExist{args: map[string]interface{}{"name": username}}
 	}
 
 	source, err := GetLoginSourceByID(loginSourceID)

+ 21 - 1
internal/db/milestone.go

@@ -14,6 +14,7 @@ import (
 	api "github.com/gogs/go-gogs-client"
 
 	"gogs.io/gogs/internal/conf"
+	"gogs.io/gogs/internal/errutil"
 )
 
 // Milestone represents a milestone of repository.
@@ -130,6 +131,25 @@ func NewMilestone(m *Milestone) (err error) {
 	return sess.Commit()
 }
 
+var _ errutil.NotFound = (*ErrMilestoneNotExist)(nil)
+
+type ErrMilestoneNotExist struct {
+	args map[string]interface{}
+}
+
+func IsErrMilestoneNotExist(err error) bool {
+	_, ok := err.(ErrMilestoneNotExist)
+	return ok
+}
+
+func (err ErrMilestoneNotExist) Error() string {
+	return fmt.Sprintf("milestone does not exist: %v", err.args)
+}
+
+func (ErrMilestoneNotExist) NotFound() bool {
+	return true
+}
+
 func getMilestoneByRepoID(e Engine, repoID, id int64) (*Milestone, error) {
 	m := &Milestone{
 		ID:     id,
@@ -139,7 +159,7 @@ func getMilestoneByRepoID(e Engine, repoID, id int64) (*Milestone, error) {
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, ErrMilestoneNotExist{id, repoID}
+		return nil, ErrMilestoneNotExist{args: map[string]interface{}{"repoID": repoID, "milestoneID": id}}
 	}
 	return m, nil
 }

+ 22 - 2
internal/db/org_team.go

@@ -11,6 +11,7 @@ import (
 	"xorm.io/xorm"
 
 	"gogs.io/gogs/internal/db/errors"
+	"gogs.io/gogs/internal/errutil"
 )
 
 const OWNER_TEAM = "Owners"
@@ -266,6 +267,25 @@ func NewTeam(t *Team) error {
 	return sess.Commit()
 }
 
+var _ errutil.NotFound = (*ErrTeamNotExist)(nil)
+
+type ErrTeamNotExist struct {
+	args map[string]interface{}
+}
+
+func IsErrTeamNotExist(err error) bool {
+	_, ok := err.(ErrTeamNotExist)
+	return ok
+}
+
+func (err ErrTeamNotExist) Error() string {
+	return fmt.Sprintf("team does not exist: %v", err.args)
+}
+
+func (ErrTeamNotExist) NotFound() bool {
+	return true
+}
+
 func getTeamOfOrgByName(e Engine, orgID int64, name string) (*Team, error) {
 	t := &Team{
 		OrgID:     orgID,
@@ -275,7 +295,7 @@ func getTeamOfOrgByName(e Engine, orgID int64, name string) (*Team, error) {
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, errors.TeamNotExist{Name: name}
+		return nil, ErrTeamNotExist{args: map[string]interface{}{"orgID": orgID, "name": name}}
 	}
 	return t, nil
 }
@@ -291,7 +311,7 @@ func getTeamByID(e Engine, teamID int64) (*Team, error) {
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, errors.TeamNotExist{TeamID: teamID}
+		return nil, ErrTeamNotExist{args: map[string]interface{}{"teamID": teamID}}
 	}
 	return t, nil
 }

+ 33 - 9
internal/db/pull.go

@@ -19,7 +19,7 @@ import (
 	api "github.com/gogs/go-gogs-client"
 
 	"gogs.io/gogs/internal/conf"
-	"gogs.io/gogs/internal/db/errors"
+	"gogs.io/gogs/internal/errutil"
 	"gogs.io/gogs/internal/osutil"
 	"gogs.io/gogs/internal/process"
 	"gogs.io/gogs/internal/sync"
@@ -89,25 +89,25 @@ func (pr *PullRequest) AfterSet(colName string, _ xorm.Cell) {
 func (pr *PullRequest) loadAttributes(e Engine) (err error) {
 	if pr.HeadRepo == nil {
 		pr.HeadRepo, err = getRepositoryByID(e, pr.HeadRepoID)
-		if err != nil && !errors.IsRepoNotExist(err) {
-			return fmt.Errorf("getRepositoryByID.(HeadRepo) [%d]: %v", pr.HeadRepoID, err)
+		if err != nil && !IsErrRepoNotExist(err) {
+			return fmt.Errorf("get head repository by ID: %v", err)
 		}
 	}
 
 	if pr.BaseRepo == nil {
 		pr.BaseRepo, err = getRepositoryByID(e, pr.BaseRepoID)
 		if err != nil {
-			return fmt.Errorf("getRepositoryByID.(BaseRepo) [%d]: %v", pr.BaseRepoID, err)
+			return fmt.Errorf("get base repository by ID: %v", err)
 		}
 	}
 
 	if pr.HasMerged && pr.Merger == nil {
 		pr.Merger, err = getUserByID(e, pr.MergerID)
-		if errors.IsUserNotExist(err) {
+		if IsErrUserNotExist(err) {
 			pr.MergerID = -1
 			pr.Merger = NewGhostUser()
 		} else if err != nil {
-			return fmt.Errorf("getUserByID [%d]: %v", pr.MergerID, err)
+			return fmt.Errorf("get merger by ID: %v", err)
 		}
 	}
 
@@ -521,7 +521,12 @@ func GetUnmergedPullRequest(headRepoID, baseRepoID int64, headBranch, baseBranch
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, ErrPullRequestNotExist{0, 0, headRepoID, baseRepoID, headBranch, baseBranch}
+		return nil, ErrPullRequestNotExist{args: map[string]interface{}{
+			"headRepoID": headRepoID,
+			"baseRepoID": baseRepoID,
+			"headBranch": headBranch,
+			"baseBranch": baseBranch,
+		}}
 	}
 
 	return pr, nil
@@ -545,13 +550,32 @@ func GetUnmergedPullRequestsByBaseInfo(repoID int64, branch string) ([]*PullRequ
 		Join("INNER", "issue", "issue.id=pull_request.issue_id").Find(&prs)
 }
 
+var _ errutil.NotFound = (*ErrPullRequestNotExist)(nil)
+
+type ErrPullRequestNotExist struct {
+	args map[string]interface{}
+}
+
+func IsErrPullRequestNotExist(err error) bool {
+	_, ok := err.(ErrPullRequestNotExist)
+	return ok
+}
+
+func (err ErrPullRequestNotExist) Error() string {
+	return fmt.Sprintf("pull request does not exist: %v", err.args)
+}
+
+func (ErrPullRequestNotExist) NotFound() bool {
+	return true
+}
+
 func getPullRequestByID(e Engine, id int64) (*PullRequest, error) {
 	pr := new(PullRequest)
 	has, err := e.ID(id).Get(pr)
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, ErrPullRequestNotExist{id, 0, 0, 0, "", ""}
+		return nil, ErrPullRequestNotExist{args: map[string]interface{}{"pullRequestID": id}}
 	}
 	return pr, pr.loadAttributes(e)
 }
@@ -569,7 +593,7 @@ func getPullRequestByIssueID(e Engine, issueID int64) (*PullRequest, error) {
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, ErrPullRequestNotExist{0, issueID, 0, 0, "", ""}
+		return nil, ErrPullRequestNotExist{args: map[string]interface{}{"issueID": issueID}}
 	}
 	return pr, pr.loadAttributes(e)
 }

+ 23 - 4
internal/db/release.go

@@ -16,7 +16,7 @@ import (
 	"github.com/gogs/git-module"
 	api "github.com/gogs/go-gogs-client"
 
-	"gogs.io/gogs/internal/db/errors"
+	"gogs.io/gogs/internal/errutil"
 	"gogs.io/gogs/internal/process"
 )
 
@@ -68,7 +68,7 @@ func (r *Release) loadAttributes(e Engine) (err error) {
 	if r.Publisher == nil {
 		r.Publisher, err = getUserByID(e, r.PublisherID)
 		if err != nil {
-			if errors.IsUserNotExist(err) {
+			if IsErrUserNotExist(err) {
 				r.PublisherID = -1
 				r.Publisher = NewGhostUser()
 			} else {
@@ -206,13 +206,32 @@ func NewRelease(gitRepo *git.Repository, r *Release, uuids []string) error {
 	return nil
 }
 
+var _ errutil.NotFound = (*ErrReleaseNotExist)(nil)
+
+type ErrReleaseNotExist struct {
+	args map[string]interface{}
+}
+
+func IsErrReleaseNotExist(err error) bool {
+	_, ok := err.(ErrReleaseNotExist)
+	return ok
+}
+
+func (err ErrReleaseNotExist) Error() string {
+	return fmt.Sprintf("release does not exist: %v", err.args)
+}
+
+func (ErrReleaseNotExist) NotFound() bool {
+	return true
+}
+
 // GetRelease returns release by given ID.
 func GetRelease(repoID int64, tagName string) (*Release, error) {
 	isExist, err := IsReleaseExist(repoID, tagName)
 	if err != nil {
 		return nil, err
 	} else if !isExist {
-		return nil, ErrReleaseNotExist{0, tagName}
+		return nil, ErrReleaseNotExist{args: map[string]interface{}{"tag": tagName}}
 	}
 
 	r := &Release{RepoID: repoID, LowerTagName: strings.ToLower(tagName)}
@@ -230,7 +249,7 @@ func GetReleaseByID(id int64) (*Release, error) {
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, ErrReleaseNotExist{id, ""}
+		return nil, ErrReleaseNotExist{args: map[string]interface{}{"releaseID": id}}
 	}
 
 	return r, r.LoadAttributes()

+ 44 - 11
internal/db/repo.go

@@ -33,6 +33,7 @@ import (
 	"gogs.io/gogs/internal/avatar"
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/db/errors"
+	"gogs.io/gogs/internal/errutil"
 	"gogs.io/gogs/internal/markup"
 	"gogs.io/gogs/internal/osutil"
 	"gogs.io/gogs/internal/process"
@@ -248,11 +249,11 @@ func (repo *Repository) loadAttributes(e Engine) (err error) {
 	if repo.IsFork && repo.BaseRepo == nil {
 		repo.BaseRepo, err = getRepositoryByID(e, repo.ForkID)
 		if err != nil {
-			if errors.IsRepoNotExist(err) {
+			if IsErrRepoNotExist(err) {
 				repo.IsFork = false
 				repo.ForkID = 0
 			} else {
-				return fmt.Errorf("getRepositoryByID [%d]: %v", repo.ForkID, err)
+				return fmt.Errorf("get fork repository by ID: %v", err)
 			}
 		}
 	}
@@ -1104,10 +1105,23 @@ func createRepository(e *xorm.Session, doer, owner *User, repo *Repository) (err
 	return repo.loadAttributes(e)
 }
 
+type ErrReachLimitOfRepo struct {
+	Limit int
+}
+
+func IsErrReachLimitOfRepo(err error) bool {
+	_, ok := err.(ErrReachLimitOfRepo)
+	return ok
+}
+
+func (err ErrReachLimitOfRepo) Error() string {
+	return fmt.Sprintf("user has reached maximum limit of repositories [limit: %d]", err.Limit)
+}
+
 // CreateRepository creates a repository for given user or organization.
 func CreateRepository(doer, owner *User, opts CreateRepoOptions) (_ *Repository, err error) {
 	if !owner.CanCreateRepo() {
-		return nil, errors.ReachLimitOfRepo{Limit: owner.RepoCreationNum()}
+		return nil, ErrReachLimitOfRepo{Limit: owner.RepoCreationNum()}
 	}
 
 	repo := &Repository{
@@ -1481,17 +1495,17 @@ func UpdateRepository(repo *Repository, visibilityChanged bool) (err error) {
 }
 
 // DeleteRepository deletes a repository for a user or organization.
-func DeleteRepository(uid, repoID int64) error {
-	repo := &Repository{ID: repoID, OwnerID: uid}
+func DeleteRepository(ownerID, repoID int64) error {
+	repo := &Repository{ID: repoID, OwnerID: ownerID}
 	has, err := x.Get(repo)
 	if err != nil {
 		return err
 	} else if !has {
-		return errors.RepoNotExist{ID: repoID, UserID: uid}
+		return ErrRepoNotExist{args: map[string]interface{}{"ownerID": ownerID, "repoID": repoID}}
 	}
 
 	// In case is a organization.
-	org, err := GetUserByID(uid)
+	org, err := GetUserByID(ownerID)
 	if err != nil {
 		return err
 	}
@@ -1571,7 +1585,7 @@ func DeleteRepository(uid, repoID int64) error {
 		}
 	}
 
-	if _, err = sess.Exec("UPDATE `user` SET num_repos=num_repos-1 WHERE id=?", uid); err != nil {
+	if _, err = sess.Exec("UPDATE `user` SET num_repos=num_repos-1 WHERE id=?", ownerID); err != nil {
 		return err
 	}
 
@@ -1616,6 +1630,25 @@ func GetRepositoryByRef(ref string) (*Repository, error) {
 	return GetRepositoryByName(user.ID, repoName)
 }
 
+var _ errutil.NotFound = (*ErrRepoNotExist)(nil)
+
+type ErrRepoNotExist struct {
+	args map[string]interface{}
+}
+
+func IsErrRepoNotExist(err error) bool {
+	_, ok := err.(ErrRepoNotExist)
+	return ok
+}
+
+func (err ErrRepoNotExist) Error() string {
+	return fmt.Sprintf("repository does not exist: %v", err.args)
+}
+
+func (ErrRepoNotExist) NotFound() bool {
+	return true
+}
+
 // GetRepositoryByName returns the repository by given name under user if exists.
 func GetRepositoryByName(ownerID int64, name string) (*Repository, error) {
 	repo := &Repository{
@@ -1626,7 +1659,7 @@ func GetRepositoryByName(ownerID int64, name string) (*Repository, error) {
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, errors.RepoNotExist{UserID: ownerID, Name: name}
+		return nil, ErrRepoNotExist{args: map[string]interface{}{"ownerID": ownerID, "name": name}}
 	}
 	return repo, repo.LoadAttributes()
 }
@@ -1637,7 +1670,7 @@ func getRepositoryByID(e Engine, id int64) (*Repository, error) {
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, errors.RepoNotExist{ID: id}
+		return nil, ErrRepoNotExist{args: map[string]interface{}{"repoID": id}}
 	}
 	return repo, repo.loadAttributes(e)
 }
@@ -2361,7 +2394,7 @@ func HasForkedRepo(ownerID, repoID int64) (*Repository, bool, error) {
 // ForkRepository creates a fork of target repository under another user domain.
 func ForkRepository(doer, owner *User, baseRepo *Repository, name, desc string) (_ *Repository, err error) {
 	if !owner.CanCreateRepo() {
-		return nil, errors.ReachLimitOfRepo{Limit: owner.RepoCreationNum()}
+		return nil, ErrReachLimitOfRepo{Limit: owner.RepoCreationNum()}
 	}
 
 	repo := &Repository{

+ 22 - 3
internal/db/repo_branch.go

@@ -11,7 +11,7 @@ import (
 	"github.com/gogs/git-module"
 	"github.com/unknwon/com"
 
-	"gogs.io/gogs/internal/db/errors"
+	"gogs.io/gogs/internal/errutil"
 	"gogs.io/gogs/internal/tool"
 )
 
@@ -44,9 +44,28 @@ func GetBranchesByPath(path string) ([]*Branch, error) {
 	return branches, nil
 }
 
+var _ errutil.NotFound = (*ErrBranchNotExist)(nil)
+
+type ErrBranchNotExist struct {
+	args map[string]interface{}
+}
+
+func IsErrBranchNotExist(err error) bool {
+	_, ok := err.(ErrBranchNotExist)
+	return ok
+}
+
+func (err ErrBranchNotExist) Error() string {
+	return fmt.Sprintf("branch does not exist: %v", err.args)
+}
+
+func (ErrBranchNotExist) NotFound() bool {
+	return true
+}
+
 func (repo *Repository) GetBranch(name string) (*Branch, error) {
 	if !git.RepoHasBranch(repo.RepoPath(), name) {
-		return nil, errors.ErrBranchNotExist{Name: name}
+		return nil, ErrBranchNotExist{args: map[string]interface{}{"name": name}}
 	}
 	return &Branch{
 		RepoPath: repo.RepoPath(),
@@ -102,7 +121,7 @@ func GetProtectBranchOfRepoByName(repoID int64, name string) (*ProtectBranch, er
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, errors.ErrBranchNotExist{Name: name}
+		return nil, ErrBranchNotExist{args: map[string]interface{}{"name": name}}
 	}
 	return protectBranch, nil
 }

+ 22 - 2
internal/db/ssh_key.go

@@ -24,6 +24,7 @@ import (
 	"xorm.io/xorm"
 
 	"gogs.io/gogs/internal/conf"
+	"gogs.io/gogs/internal/errutil"
 	"gogs.io/gogs/internal/process"
 )
 
@@ -684,6 +685,25 @@ func AddDeployKey(repoID int64, name, content string) (*DeployKey, error) {
 	return key, sess.Commit()
 }
 
+var _ errutil.NotFound = (*ErrDeployKeyNotExist)(nil)
+
+type ErrDeployKeyNotExist struct {
+	args map[string]interface{}
+}
+
+func IsErrDeployKeyNotExist(err error) bool {
+	_, ok := err.(ErrDeployKeyNotExist)
+	return ok
+}
+
+func (err ErrDeployKeyNotExist) Error() string {
+	return fmt.Sprintf("deploy key does not exist: %v", err.args)
+}
+
+func (ErrDeployKeyNotExist) NotFound() bool {
+	return true
+}
+
 // GetDeployKeyByID returns deploy key by given ID.
 func GetDeployKeyByID(id int64) (*DeployKey, error) {
 	key := new(DeployKey)
@@ -691,7 +711,7 @@ func GetDeployKeyByID(id int64) (*DeployKey, error) {
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, ErrDeployKeyNotExist{id, 0, 0}
+		return nil, ErrDeployKeyNotExist{args: map[string]interface{}{"deployKeyID": id}}
 	}
 	return key, nil
 }
@@ -706,7 +726,7 @@ func GetDeployKeyByRepo(keyID, repoID int64) (*DeployKey, error) {
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, ErrDeployKeyNotExist{0, keyID, repoID}
+		return nil, ErrDeployKeyNotExist{args: map[string]interface{}{"keyID": keyID, "repoID": repoID}}
 	}
 	return key, nil
 }

+ 28 - 8
internal/db/user.go

@@ -31,6 +31,7 @@ import (
 	"gogs.io/gogs/internal/avatar"
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/db/errors"
+	"gogs.io/gogs/internal/errutil"
 	"gogs.io/gogs/internal/tool"
 )
 
@@ -606,8 +607,8 @@ func parseUserFromCode(code string) (user *User) {
 	if b, err := hex.DecodeString(hexStr); err == nil {
 		if user, err = GetUserByName(string(b)); user != nil {
 			return user
-		} else if !errors.IsUserNotExist(err) {
-			log.Error("GetUserByName: %v", err)
+		} else if !IsErrUserNotExist(err) {
+			log.Error("Failed to get user by name %q: %v", string(b), err)
 		}
 	}
 
@@ -890,13 +891,32 @@ func GetUserByKeyID(keyID int64) (*User, error) {
 	return user, nil
 }
 
+var _ errutil.NotFound = (*ErrUserNotExist)(nil)
+
+type ErrUserNotExist struct {
+	args map[string]interface{}
+}
+
+func IsErrUserNotExist(err error) bool {
+	_, ok := err.(ErrUserNotExist)
+	return ok
+}
+
+func (err ErrUserNotExist) Error() string {
+	return fmt.Sprintf("user does not exist: %v", err.args)
+}
+
+func (ErrUserNotExist) NotFound() bool {
+	return true
+}
+
 func getUserByID(e Engine, id int64) (*User, error) {
 	u := new(User)
 	has, err := e.ID(id).Get(u)
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, errors.UserNotExist{UserID: id}
+		return nil, ErrUserNotExist{args: map[string]interface{}{"userID": id}}
 	}
 	return u, nil
 }
@@ -912,7 +932,7 @@ func GetAssigneeByID(repo *Repository, userID int64) (*User, error) {
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, errors.UserNotExist{UserID: userID}
+		return nil, ErrUserNotExist{args: map[string]interface{}{"userID": userID}}
 	}
 	return GetUserByID(userID)
 }
@@ -920,14 +940,14 @@ func GetAssigneeByID(repo *Repository, userID int64) (*User, error) {
 // GetUserByName returns a user by given name.
 func GetUserByName(name string) (*User, error) {
 	if len(name) == 0 {
-		return nil, errors.UserNotExist{Name: name}
+		return nil, ErrUserNotExist{args: map[string]interface{}{"name": name}}
 	}
 	u := &User{LowerName: strings.ToLower(name)}
 	has, err := x.Get(u)
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, errors.UserNotExist{Name: name}
+		return nil, ErrUserNotExist{args: map[string]interface{}{"name": name}}
 	}
 	return u, nil
 }
@@ -999,7 +1019,7 @@ func ValidateCommitsWithEmails(oldCommits []*git.Commit) []*UserCommit {
 // GetUserByEmail returns the user object by given e-mail if exists.
 func GetUserByEmail(email string) (*User, error) {
 	if len(email) == 0 {
-		return nil, errors.UserNotExist{Name: "email"}
+		return nil, ErrUserNotExist{args: map[string]interface{}{"email": email}}
 	}
 
 	email = strings.ToLower(email)
@@ -1023,7 +1043,7 @@ func GetUserByEmail(email string) (*User, error) {
 		return GetUserByID(emailAddress.UID)
 	}
 
-	return nil, errors.UserNotExist{Name: email}
+	return nil, ErrUserNotExist{args: map[string]interface{}{"email": email}}
 }
 
 type SearchUserOptions struct {

+ 1 - 1
internal/db/user_mail.go

@@ -181,7 +181,7 @@ func MakeEmailPrimary(userID int64, email *EmailAddress) error {
 	if err != nil {
 		return err
 	} else if !has {
-		return errors.UserNotExist{UserID: email.UID}
+		return ErrUserNotExist{args: map[string]interface{}{"userID": email.UID}}
 	}
 
 	// Make sure the former primary email doesn't disappear.

+ 41 - 3
internal/db/webhook.go

@@ -22,7 +22,7 @@ import (
 	api "github.com/gogs/go-gogs-client"
 
 	"gogs.io/gogs/internal/conf"
-	"gogs.io/gogs/internal/db/errors"
+	"gogs.io/gogs/internal/errutil"
 	"gogs.io/gogs/internal/httplib"
 	"gogs.io/gogs/internal/sync"
 )
@@ -235,6 +235,25 @@ func CreateWebhook(w *Webhook) error {
 	return err
 }
 
+var _ errutil.NotFound = (*ErrWebhookNotExist)(nil)
+
+type ErrWebhookNotExist struct {
+	args map[string]interface{}
+}
+
+func IsErrWebhookNotExist(err error) bool {
+	_, ok := err.(ErrWebhookNotExist)
+	return ok
+}
+
+func (err ErrWebhookNotExist) Error() string {
+	return fmt.Sprintf("webhook does not exist: %v", err.args)
+}
+
+func (ErrWebhookNotExist) NotFound() bool {
+	return true
+}
+
 // getWebhook uses argument bean as query condition,
 // ID must be specified and do not assign unnecessary fields.
 func getWebhook(bean *Webhook) (*Webhook, error) {
@@ -242,7 +261,7 @@ func getWebhook(bean *Webhook) (*Webhook, error) {
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, errors.WebhookNotExist{ID: bean.ID}
+		return nil, ErrWebhookNotExist{args: map[string]interface{}{"webhookID": bean.ID}}
 	}
 	return bean, nil
 }
@@ -499,6 +518,25 @@ func createHookTask(e Engine, t *HookTask) error {
 	return err
 }
 
+var _ errutil.NotFound = (*ErrHookTaskNotExist)(nil)
+
+type ErrHookTaskNotExist struct {
+	args map[string]interface{}
+}
+
+func IsHookTaskNotExist(err error) bool {
+	_, ok := err.(ErrHookTaskNotExist)
+	return ok
+}
+
+func (err ErrHookTaskNotExist) Error() string {
+	return fmt.Sprintf("hook task does not exist: %v", err.args)
+}
+
+func (ErrHookTaskNotExist) NotFound() bool {
+	return true
+}
+
 // GetHookTaskOfWebhookByUUID returns hook task of given webhook by UUID.
 func GetHookTaskOfWebhookByUUID(webhookID int64, uuid string) (*HookTask, error) {
 	hookTask := &HookTask{
@@ -509,7 +547,7 @@ func GetHookTaskOfWebhookByUUID(webhookID int64, uuid string) (*HookTask, error)
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, errors.HookTaskNotExist{HookID: webhookID, UUID: uuid}
+		return nil, ErrHookTaskNotExist{args: map[string]interface{}{"webhookID": webhookID, "uuid": uuid}}
 	}
 	return hookTask, nil
 }

+ 16 - 0
internal/errutil/errutil.go

@@ -0,0 +1,16 @@
+// Copyright 2020 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package errutil
+
+// NotFound represents a not found error.
+type NotFound interface {
+	NotFound() bool
+}
+
+// IsNotFound returns true if the error is a not found error.
+func IsNotFound(err error) bool {
+	e, ok := err.(NotFound)
+	return ok && e.NotFound()
+}

+ 25 - 5
internal/gitutil/error.go

@@ -6,8 +6,33 @@ package gitutil
 
 import (
 	"github.com/gogs/git-module"
+
+	"gogs.io/gogs/internal/errutil"
 )
 
+var _ errutil.NotFound = (*Error)(nil)
+
+// Error is a wrapper of a Git error, which handles not found.
+type Error struct {
+	error
+}
+
+func (e Error) NotFound() bool {
+	return IsErrSubmoduleNotExist(e.error) ||
+		IsErrRevisionNotExist(e.error)
+
+}
+
+// NewError wraps given error.
+func NewError(err error) error {
+	return Error{error: err}
+}
+
+// IsErrSubmoduleNotExist returns true if the error is git.ErrSubmoduleNotExist.
+func IsErrSubmoduleNotExist(err error) bool {
+	return err == git.ErrSubmoduleNotExist
+}
+
 // IsErrRevisionNotExist returns true if the error is git.ErrRevisionNotExist.
 func IsErrRevisionNotExist(err error) bool {
 	return err == git.ErrRevisionNotExist
@@ -17,8 +42,3 @@ func IsErrRevisionNotExist(err error) bool {
 func IsErrNoMergeBase(err error) bool {
 	return err == git.ErrNoMergeBase
 }
-
-// IsErrSubmoduleNotExist returns true if the error is git.ErrSubmoduleNotExist.
-func IsErrSubmoduleNotExist(err error) bool {
-	return err == git.ErrSubmoduleNotExist
-}

+ 27 - 0
internal/osutil/error.go

@@ -0,0 +1,27 @@
+// Copyright 2020 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package osutil
+
+import (
+	"os"
+
+	"gogs.io/gogs/internal/errutil"
+)
+
+var _ errutil.NotFound = (*Error)(nil)
+
+// Error is a wrapper of an OS error, which handles not found.
+type Error struct {
+	error
+}
+
+func (e Error) NotFound() bool {
+	return e.error == os.ErrNotExist
+}
+
+// NewError wraps given error.
+func NewError(err error) error {
+	return Error{error: err}
+}

+ 2 - 2
internal/route/admin/admin.go

@@ -163,7 +163,7 @@ func Dashboard(c *context.Context) {
 		} else {
 			c.Flash.Success(success)
 		}
-		c.SubURLRedirect("/admin")
+		c.RedirectSubpath("/admin")
 		return
 	}
 
@@ -239,5 +239,5 @@ func Monitor(c *context.Context) {
 	c.Data["PageIsAdminMonitor"] = true
 	c.Data["Processes"] = process.Processes
 	c.Data["Entries"] = cron.ListTasks()
-	c.HTML(200, MONITOR)
+	c.Success( MONITOR)
 }

+ 8 - 8
internal/route/admin/auths.go

@@ -34,7 +34,7 @@ func Authentications(c *context.Context) {
 	var err error
 	c.Data["Sources"], err = db.LoginSources()
 	if err != nil {
-		c.ServerError("LoginSources", err)
+		c.Error(err, "list login sources")
 		return
 	}
 
@@ -146,7 +146,7 @@ func NewAuthSourcePost(c *context.Context, f form.Authentication) {
 			APIEndpoint: strings.TrimSuffix(f.GitHubAPIEndpoint, "/") + "/",
 		}
 	default:
-		c.Error(http.StatusBadRequest)
+		c.Status(http.StatusBadRequest)
 		return
 	}
 	c.Data["HasTLS"] = hasTLS
@@ -167,7 +167,7 @@ func NewAuthSourcePost(c *context.Context, f form.Authentication) {
 			c.FormErr("Name")
 			c.RenderWithErr(c.Tr("admin.auths.login_source_exist", err.(db.ErrLoginSourceAlreadyExist).Name), AUTH_NEW, f)
 		} else {
-			c.ServerError("CreateSource", err)
+			c.Error(err, "create login source")
 		}
 		return
 	}
@@ -188,7 +188,7 @@ func EditAuthSource(c *context.Context) {
 
 	source, err := db.GetLoginSourceByID(c.ParamsInt64(":authid"))
 	if err != nil {
-		c.ServerError("GetLoginSourceByID", err)
+		c.Error(err, "get login source by ID")
 		return
 	}
 	c.Data["Source"] = source
@@ -206,7 +206,7 @@ func EditAuthSourcePost(c *context.Context, f form.Authentication) {
 
 	source, err := db.GetLoginSourceByID(c.ParamsInt64(":authid"))
 	if err != nil {
-		c.ServerError("GetLoginSourceByID", err)
+		c.Error(err, "get login source by ID")
 		return
 	}
 	c.Data["Source"] = source
@@ -232,7 +232,7 @@ func EditAuthSourcePost(c *context.Context, f form.Authentication) {
 			APIEndpoint: strings.TrimSuffix(f.GitHubAPIEndpoint, "/") + "/",
 		}
 	default:
-		c.Error(http.StatusBadRequest)
+		c.Status(http.StatusBadRequest)
 		return
 	}
 
@@ -241,7 +241,7 @@ func EditAuthSourcePost(c *context.Context, f form.Authentication) {
 	source.IsDefault = f.IsDefault
 	source.Cfg = config
 	if err := db.UpdateLoginSource(source); err != nil {
-		c.ServerError("UpdateLoginSource", err)
+		c.Error(err, "update login source")
 		return
 	}
 
@@ -254,7 +254,7 @@ func EditAuthSourcePost(c *context.Context, f form.Authentication) {
 func DeleteAuthSource(c *context.Context) {
 	source, err := db.GetLoginSourceByID(c.ParamsInt64(":authid"))
 	if err != nil {
-		c.ServerError("GetLoginSourceByID", err)
+		c.Error(err, "get login source by ID")
 		return
 	}
 

+ 8 - 6
internal/route/admin/notice.go

@@ -5,6 +5,8 @@
 package admin
 
 import (
+	"net/http"
+
 	"github.com/unknwon/com"
 	"github.com/unknwon/paginater"
 	log "unknwon.dev/clog/v2"
@@ -19,7 +21,7 @@ const (
 )
 
 func Notices(c *context.Context) {
-	c.Data["Title"] = c.Tr("admin.notices")
+	c.Title("admin.notices")
 	c.Data["PageIsAdmin"] = true
 	c.Data["PageIsAdminNotices"] = true
 
@@ -32,13 +34,13 @@ func Notices(c *context.Context) {
 
 	notices, err := db.Notices(page, conf.UI.Admin.NoticePagingNum)
 	if err != nil {
-		c.Handle(500, "Notices", err)
+		c.Error(err, "list notices")
 		return
 	}
 	c.Data["Notices"] = notices
 
 	c.Data["Total"] = total
-	c.HTML(200, NOTICES)
+	c.Success(NOTICES)
 }
 
 func DeleteNotices(c *context.Context) {
@@ -53,16 +55,16 @@ func DeleteNotices(c *context.Context) {
 
 	if err := db.DeleteNoticesByIDs(ids); err != nil {
 		c.Flash.Error("DeleteNoticesByIDs: " + err.Error())
-		c.Status(500)
+		c.Status(http.StatusInternalServerError)
 	} else {
 		c.Flash.Success(c.Tr("admin.notices.delete_success"))
-		c.Status(200)
+		c.Status(http.StatusOK)
 	}
 }
 
 func EmptyNotices(c *context.Context) {
 	if err := db.DeleteNotices(0, 0); err != nil {
-		c.Handle(500, "DeleteNotices", err)
+		c.Error(err,"delete notices")
 		return
 	}
 

+ 7 - 7
internal/route/admin/repos.go

@@ -37,7 +37,7 @@ func Repos(c *context.Context) {
 	if len(keyword) == 0 {
 		repos, err = db.Repositories(page, conf.UI.Admin.RepoPagingNum)
 		if err != nil {
-			c.Handle(500, "Repositories", err)
+			c.Error(err, "list repositories")
 			return
 		}
 		count = db.CountRepositories(true)
@@ -50,7 +50,7 @@ func Repos(c *context.Context) {
 			PageSize: conf.UI.Admin.RepoPagingNum,
 		})
 		if err != nil {
-			c.Handle(500, "SearchRepositoryByName", err)
+			c.Error(err, "search repository by name")
 			return
 		}
 	}
@@ -59,29 +59,29 @@ func Repos(c *context.Context) {
 	c.Data["Page"] = paginater.New(int(count), conf.UI.Admin.RepoPagingNum, page, 5)
 
 	if err = db.RepositoryList(repos).LoadAttributes(); err != nil {
-		c.Handle(500, "LoadAttributes", err)
+		c.Error(err, "load attributes")
 		return
 	}
 	c.Data["Repos"] = repos
 
-	c.HTML(200, REPOS)
+	c.Success(REPOS)
 }
 
 func DeleteRepo(c *context.Context) {
 	repo, err := db.GetRepositoryByID(c.QueryInt64("id"))
 	if err != nil {
-		c.Handle(500, "GetRepositoryByID", err)
+		c.Error(err, "get repository by ID")
 		return
 	}
 
 	if err := db.DeleteRepository(repo.MustOwner().ID, repo.ID); err != nil {
-		c.Handle(500, "DeleteRepository", err)
+		c.Error(err, "delete repository")
 		return
 	}
 	log.Trace("Repository deleted: %s/%s", repo.MustOwner().Name, repo.Name)
 
 	c.Flash.Success(c.Tr("repo.settings.deletion_success"))
-	c.JSON(200, map[string]interface{}{
+	c.JSONSuccess(map[string]interface{}{
 		"redirect": conf.Server.Subpath + "/admin/repos?page=" + c.Query("page"),
 	})
 }

+ 17 - 17
internal/route/admin/users.go

@@ -48,13 +48,13 @@ func NewUser(c *context.Context) {
 
 	sources, err := db.LoginSources()
 	if err != nil {
-		c.Handle(500, "LoginSources", err)
+		c.Error(err, "list login sources")
 		return
 	}
 	c.Data["Sources"] = sources
 
 	c.Data["CanSendEmail"] = conf.Email.Enabled
-	c.HTML(200, USER_NEW)
+	c.Success(USER_NEW)
 }
 
 func NewUserPost(c *context.Context, f form.AdminCrateUser) {
@@ -64,7 +64,7 @@ func NewUserPost(c *context.Context, f form.AdminCrateUser) {
 
 	sources, err := db.LoginSources()
 	if err != nil {
-		c.Handle(500, "LoginSources", err)
+		c.Error(err, "list login sources")
 		return
 	}
 	c.Data["Sources"] = sources
@@ -72,7 +72,7 @@ func NewUserPost(c *context.Context, f form.AdminCrateUser) {
 	c.Data["CanSendEmail"] = conf.Email.Enabled
 
 	if c.HasError() {
-		c.HTML(200, USER_NEW)
+		c.Success(USER_NEW)
 		return
 	}
 
@@ -108,7 +108,7 @@ func NewUserPost(c *context.Context, f form.AdminCrateUser) {
 			c.Data["Err_UserName"] = true
 			c.RenderWithErr(c.Tr("user.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), USER_NEW, &f)
 		default:
-			c.Handle(500, "CreateUser", err)
+			c.Error(err, "create user")
 		}
 		return
 	}
@@ -126,7 +126,7 @@ func NewUserPost(c *context.Context, f form.AdminCrateUser) {
 func prepareUserInfo(c *context.Context) *db.User {
 	u, err := db.GetUserByID(c.ParamsInt64(":userid"))
 	if err != nil {
-		c.Handle(500, "GetUserByID", err)
+		c.Error(err, "get user by ID")
 		return nil
 	}
 	c.Data["User"] = u
@@ -134,7 +134,7 @@ func prepareUserInfo(c *context.Context) *db.User {
 	if u.LoginSource > 0 {
 		c.Data["LoginSource"], err = db.GetLoginSourceByID(u.LoginSource)
 		if err != nil {
-			c.Handle(500, "GetLoginSourceByID", err)
+			c.Error(err, "get login source by ID")
 			return nil
 		}
 	} else {
@@ -143,7 +143,7 @@ func prepareUserInfo(c *context.Context) *db.User {
 
 	sources, err := db.LoginSources()
 	if err != nil {
-		c.Handle(500, "LoginSources", err)
+		c.Error(err, "list login sources")
 		return nil
 	}
 	c.Data["Sources"] = sources
@@ -162,7 +162,7 @@ func EditUser(c *context.Context) {
 		return
 	}
 
-	c.HTML(200, USER_EDIT)
+	c.Success(USER_EDIT)
 }
 
 func EditUserPost(c *context.Context, f form.AdminEditUser) {
@@ -177,7 +177,7 @@ func EditUserPost(c *context.Context, f form.AdminEditUser) {
 	}
 
 	if c.HasError() {
-		c.HTML(200, USER_EDIT)
+		c.Success(USER_EDIT)
 		return
 	}
 
@@ -196,7 +196,7 @@ func EditUserPost(c *context.Context, f form.AdminEditUser) {
 		u.Passwd = f.Password
 		var err error
 		if u.Salt, err = db.GetUserSalt(); err != nil {
-			c.Handle(500, "UpdateUser", err)
+			c.Error(err, "get user salt")
 			return
 		}
 		u.EncodePasswd()
@@ -219,7 +219,7 @@ func EditUserPost(c *context.Context, f form.AdminEditUser) {
 			c.Data["Err_Email"] = true
 			c.RenderWithErr(c.Tr("form.email_been_used"), USER_EDIT, &f)
 		} else {
-			c.Handle(500, "UpdateUser", err)
+			c.Error(err, "update user")
 		}
 		return
 	}
@@ -232,7 +232,7 @@ func EditUserPost(c *context.Context, f form.AdminEditUser) {
 func DeleteUser(c *context.Context) {
 	u, err := db.GetUserByID(c.ParamsInt64(":userid"))
 	if err != nil {
-		c.Handle(500, "GetUserByID", err)
+		c.Error(err, "get user by ID")
 		return
 	}
 
@@ -240,23 +240,23 @@ func DeleteUser(c *context.Context) {
 		switch {
 		case db.IsErrUserOwnRepos(err):
 			c.Flash.Error(c.Tr("admin.users.still_own_repo"))
-			c.JSON(200, map[string]interface{}{
+			c.JSONSuccess(map[string]interface{}{
 				"redirect": conf.Server.Subpath + "/admin/users/" + c.Params(":userid"),
 			})
 		case db.IsErrUserHasOrgs(err):
 			c.Flash.Error(c.Tr("admin.users.still_has_org"))
-			c.JSON(200, map[string]interface{}{
+			c.JSONSuccess(map[string]interface{}{
 				"redirect": conf.Server.Subpath + "/admin/users/" + c.Params(":userid"),
 			})
 		default:
-			c.Handle(500, "DeleteUser", err)
+			c.Error(err, "delete user")
 		}
 		return
 	}
 	log.Trace("Account deleted by admin (%s): %s", c.User.Name, u.Name)
 
 	c.Flash.Success(c.Tr("admin.users.deletion_success"))
-	c.JSON(200, map[string]interface{}{
+	c.JSONSuccess(map[string]interface{}{
 		"redirect": conf.Server.Subpath + "/admin/users",
 	})
 }

+ 3 - 3
internal/route/api/v1/admin/org.go

@@ -6,12 +6,12 @@ package admin
 
 import (
 	api "github.com/gogs/go-gogs-client"
-	org2 "gogs.io/gogs/internal/route/api/v1/org"
-	user2 "gogs.io/gogs/internal/route/api/v1/user"
 
 	"gogs.io/gogs/internal/context"
+	"gogs.io/gogs/internal/route/api/v1/org"
+	"gogs.io/gogs/internal/route/api/v1/user"
 )
 
 func CreateOrg(c *context.APIContext, form api.CreateOrgOption) {
-	org2.CreateOrgForUser(c, form, user2.GetUserByParams(c))
+	org.CreateOrgForUser(c, form, user.GetUserByParams(c))
 }

+ 3 - 4
internal/route/api/v1/admin/org_repo.go

@@ -7,13 +7,12 @@ package admin
 import (
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
 )
 
 func GetRepositoryByParams(c *context.APIContext) *db.Repository {
 	repo, err := db.GetRepositoryByName(c.Org.Team.OrgID, c.Params(":reponame"))
 	if err != nil {
-		c.NotFoundOrServerError("GetRepositoryByName", errors.IsRepoNotExist, err)
+		c.NotFoundOrError(err, "get repository by name")
 		return nil
 	}
 	return repo
@@ -25,7 +24,7 @@ func AddTeamRepository(c *context.APIContext) {
 		return
 	}
 	if err := c.Org.Team.AddRepository(repo); err != nil {
-		c.ServerError("AddRepository", err)
+		c.Error(err, "add repository")
 		return
 	}
 
@@ -38,7 +37,7 @@ func RemoveTeamRepository(c *context.APIContext) {
 		return
 	}
 	if err := c.Org.Team.RemoveRepository(repo.ID); err != nil {
-		c.ServerError("RemoveRepository", err)
+		c.Error(err, "remove repository")
 		return
 	}
 

+ 9 - 9
internal/route/api/v1/admin/org_team.go

@@ -5,14 +5,14 @@
 package admin
 
 import (
-	convert2 "gogs.io/gogs/internal/route/api/v1/convert"
-	user2 "gogs.io/gogs/internal/route/api/v1/user"
 	"net/http"
 
 	api "github.com/gogs/go-gogs-client"
 
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
+	"gogs.io/gogs/internal/route/api/v1/convert"
+	"gogs.io/gogs/internal/route/api/v1/user"
 )
 
 func CreateTeam(c *context.APIContext, form api.CreateTeamOption) {
@@ -24,23 +24,23 @@ func CreateTeam(c *context.APIContext, form api.CreateTeamOption) {
 	}
 	if err := db.NewTeam(team); err != nil {
 		if db.IsErrTeamAlreadyExist(err) {
-			c.Error(http.StatusUnprocessableEntity, "", err)
+			c.ErrorStatus(http.StatusUnprocessableEntity, err)
 		} else {
-			c.ServerError("NewTeam", err)
+			c.Error(err, "new team")
 		}
 		return
 	}
 
-	c.JSON(http.StatusCreated, convert2.ToTeam(team))
+	c.JSON(http.StatusCreated, convert.ToTeam(team))
 }
 
 func AddTeamMember(c *context.APIContext) {
-	u := user2.GetUserByParams(c)
+	u := user.GetUserByParams(c)
 	if c.Written() {
 		return
 	}
 	if err := c.Org.Team.AddMember(u.ID); err != nil {
-		c.ServerError("AddMember", err)
+		c.Error(err, "add member")
 		return
 	}
 
@@ -48,13 +48,13 @@ func AddTeamMember(c *context.APIContext) {
 }
 
 func RemoveTeamMember(c *context.APIContext) {
-	u := user2.GetUserByParams(c)
+	u := user.GetUserByParams(c)
 	if c.Written() {
 		return
 	}
 
 	if err := c.Org.Team.RemoveMember(u.ID); err != nil {
-		c.ServerError("RemoveMember", err)
+		c.Error(err, "remove member")
 		return
 	}
 

+ 4 - 4
internal/route/api/v1/admin/repo.go

@@ -6,17 +6,17 @@ package admin
 
 import (
 	api "github.com/gogs/go-gogs-client"
-	repo2 "gogs.io/gogs/internal/route/api/v1/repo"
-	user2 "gogs.io/gogs/internal/route/api/v1/user"
 
 	"gogs.io/gogs/internal/context"
+	"gogs.io/gogs/internal/route/api/v1/repo"
+	"gogs.io/gogs/internal/route/api/v1/user"
 )
 
 func CreateRepo(c *context.APIContext, form api.CreateRepoOption) {
-	owner := user2.GetUserByParams(c)
+	owner := user.GetUserByParams(c)
 	if c.Written() {
 		return
 	}
 
-	repo2.CreateUserRepo(c, owner, form)
+	repo.CreateUserRepo(c, owner, form)
 }

+ 10 - 11
internal/route/api/v1/admin/user.go

@@ -7,9 +7,8 @@ package admin
 import (
 	"net/http"
 
-	log "unknwon.dev/clog/v2"
-
 	api "github.com/gogs/go-gogs-client"
+	log "unknwon.dev/clog/v2"
 
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/context"
@@ -27,9 +26,9 @@ func parseLoginSource(c *context.APIContext, u *db.User, sourceID int64, loginNa
 	source, err := db.GetLoginSourceByID(sourceID)
 	if err != nil {
 		if errors.IsLoginSourceNotExist(err) {
-			c.Error(http.StatusUnprocessableEntity, "", err)
+			c.ErrorStatus(http.StatusUnprocessableEntity, err)
 		} else {
-			c.ServerError("GetLoginSourceByID", err)
+			c.Error(err, "get login source by ID")
 		}
 		return
 	}
@@ -59,9 +58,9 @@ func CreateUser(c *context.APIContext, form api.CreateUserOption) {
 			db.IsErrEmailAlreadyUsed(err) ||
 			db.IsErrNameReserved(err) ||
 			db.IsErrNamePatternNotAllowed(err) {
-			c.Error(http.StatusUnprocessableEntity, "", err)
+			c.ErrorStatus(http.StatusUnprocessableEntity, err)
 		} else {
-			c.ServerError("CreateUser", err)
+			c.Error(err, "create user")
 		}
 		return
 	}
@@ -90,7 +89,7 @@ func EditUser(c *context.APIContext, form api.EditUserOption) {
 		u.Passwd = form.Password
 		var err error
 		if u.Salt, err = db.GetUserSalt(); err != nil {
-			c.ServerError("GetUserSalt", err)
+			c.Error(err, "get user salt")
 			return
 		}
 		u.EncodePasswd()
@@ -119,9 +118,9 @@ func EditUser(c *context.APIContext, form api.EditUserOption) {
 
 	if err := db.UpdateUser(u); err != nil {
 		if db.IsErrEmailAlreadyUsed(err) {
-			c.Error(http.StatusUnprocessableEntity, "", err)
+			c.ErrorStatus(http.StatusUnprocessableEntity, err)
 		} else {
-			c.ServerError("UpdateUser", err)
+			c.Error(err, "update user")
 		}
 		return
 	}
@@ -139,9 +138,9 @@ func DeleteUser(c *context.APIContext) {
 	if err := db.DeleteUser(u); err != nil {
 		if db.IsErrUserOwnRepos(err) ||
 			db.IsErrUserHasOrgs(err) {
-			c.Error(http.StatusUnprocessableEntity, "", err)
+			c.ErrorStatus(http.StatusUnprocessableEntity, err)
 		} else {
-			c.ServerError("DeleteUser", err)
+			c.Error(err, "delete user")
 		}
 		return
 	}

+ 11 - 12
internal/route/api/v1/api.go

@@ -15,7 +15,6 @@ import (
 
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
 	"gogs.io/gogs/internal/form"
 	"gogs.io/gogs/internal/route/api/v1/admin"
 	"gogs.io/gogs/internal/route/api/v1/misc"
@@ -40,7 +39,7 @@ func repoAssignment() macaron.Handler {
 		} else {
 			owner, err = db.GetUserByName(username)
 			if err != nil {
-				c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
+				c.NotFoundOrError(err, "get user by name")
 				return
 			}
 		}
@@ -48,10 +47,10 @@ func repoAssignment() macaron.Handler {
 
 		r, err := db.GetRepositoryByName(owner.ID, reponame)
 		if err != nil {
-			c.NotFoundOrServerError("GetRepositoryByName", errors.IsRepoNotExist, err)
+			c.NotFoundOrError(err, "get repository by name")
 			return
 		} else if err = r.GetOwner(); err != nil {
-			c.ServerError("GetOwner", err)
+			c.Error(err, "get owner")
 			return
 		}
 
@@ -60,7 +59,7 @@ func repoAssignment() macaron.Handler {
 		} else {
 			mode, err := db.UserAccessMode(c.UserID(), r)
 			if err != nil {
-				c.ServerError("UserAccessMode", err)
+				c.Error(err, "get user access mode")
 				return
 			}
 			c.Repo.AccessMode = mode
@@ -94,7 +93,7 @@ func orgAssignment(args ...bool) macaron.Handler {
 		if assignOrg {
 			c.Org.Organization, err = db.GetUserByName(c.Params(":orgname"))
 			if err != nil {
-				c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
+				c.NotFoundOrError(err, "get organization by name")
 				return
 			}
 		}
@@ -102,7 +101,7 @@ func orgAssignment(args ...bool) macaron.Handler {
 		if assignTeam {
 			c.Org.Team, err = db.GetTeamByID(c.ParamsInt64(":teamid"))
 			if err != nil {
-				c.NotFoundOrServerError("GetTeamByID", errors.IsTeamNotExist, err)
+				c.NotFoundOrError(err, "get team by ID")
 				return
 			}
 		}
@@ -113,7 +112,7 @@ func orgAssignment(args ...bool) macaron.Handler {
 func reqToken() macaron.Handler {
 	return func(c *context.Context) {
 		if !c.IsTokenAuth {
-			c.Error(http.StatusUnauthorized)
+			c.Status(http.StatusUnauthorized)
 			return
 		}
 	}
@@ -123,7 +122,7 @@ func reqToken() macaron.Handler {
 func reqBasicAuth() macaron.Handler {
 	return func(c *context.Context) {
 		if !c.IsBasicAuth {
-			c.Error(http.StatusUnauthorized)
+			c.Status(http.StatusUnauthorized)
 			return
 		}
 	}
@@ -133,7 +132,7 @@ func reqBasicAuth() macaron.Handler {
 func reqAdmin() macaron.Handler {
 	return func(c *context.Context) {
 		if !c.IsLogged || !c.User.IsAdmin {
-			c.Error(http.StatusForbidden)
+			c.Status(http.StatusForbidden)
 			return
 		}
 	}
@@ -143,7 +142,7 @@ func reqAdmin() macaron.Handler {
 func reqRepoWriter() macaron.Handler {
 	return func(c *context.Context) {
 		if !c.Repo.IsWriter() {
-			c.Error(http.StatusForbidden)
+			c.Status(http.StatusForbidden)
 			return
 		}
 	}
@@ -153,7 +152,7 @@ func reqRepoWriter() macaron.Handler {
 func reqRepoAdmin() macaron.Handler {
 	return func(c *context.Context) {
 		if !c.Repo.IsAdmin() {
-			c.Error(http.StatusForbidden)
+			c.Status(http.StatusForbidden)
 			return
 		}
 	}

+ 1 - 8
internal/route/api/v1/misc/markdown.go

@@ -5,8 +5,6 @@
 package misc
 
 import (
-	"net/http"
-
 	api "github.com/gogs/go-gogs-client"
 
 	"gogs.io/gogs/internal/context"
@@ -14,11 +12,6 @@ import (
 )
 
 func Markdown(c *context.APIContext, form api.MarkdownOption) {
-	if c.HasApiError() {
-		c.Error(http.StatusUnprocessableEntity, "", c.GetErrMsg())
-		return
-	}
-
 	if len(form.Text) == 0 {
 		_, _ = c.Write([]byte(""))
 		return
@@ -30,7 +23,7 @@ func Markdown(c *context.APIContext, form api.MarkdownOption) {
 func MarkdownRaw(c *context.APIContext) {
 	body, err := c.Req.Body().Bytes()
 	if err != nil {
-		c.Error(http.StatusUnprocessableEntity, "", err)
+		c.Error(err, "read body")
 		return
 	}
 	_, _ = c.Write(markup.SanitizeBytes(markup.RawMarkdown(body, "")))

+ 11 - 11
internal/route/api/v1/org/org.go

@@ -5,14 +5,14 @@
 package org
 
 import (
-	convert2 "gogs.io/gogs/internal/route/api/v1/convert"
-	user2 "gogs.io/gogs/internal/route/api/v1/user"
 	"net/http"
 
 	api "github.com/gogs/go-gogs-client"
 
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
+	"gogs.io/gogs/internal/route/api/v1/convert"
+	"gogs.io/gogs/internal/route/api/v1/user"
 )
 
 func CreateOrgForUser(c *context.APIContext, apiForm api.CreateOrgOption, user *db.User) {
@@ -33,25 +33,25 @@ func CreateOrgForUser(c *context.APIContext, apiForm api.CreateOrgOption, user *
 		if db.IsErrUserAlreadyExist(err) ||
 			db.IsErrNameReserved(err) ||
 			db.IsErrNamePatternNotAllowed(err) {
-			c.Error(http.StatusUnprocessableEntity, "", err)
+			c.ErrorStatus(http.StatusUnprocessableEntity, err)
 		} else {
-			c.ServerError("CreateOrganization", err)
+			c.Error(err, "create organization")
 		}
 		return
 	}
 
-	c.JSON(201, convert2.ToOrganization(org))
+	c.JSON(201, convert.ToOrganization(org))
 }
 
 func listUserOrgs(c *context.APIContext, u *db.User, all bool) {
 	if err := u.GetOrganizations(all); err != nil {
-		c.ServerError("GetOrganizations", err)
+		c.Error(err, "get organization")
 		return
 	}
 
 	apiOrgs := make([]*api.Organization, len(u.Orgs))
 	for i := range u.Orgs {
-		apiOrgs[i] = convert2.ToOrganization(u.Orgs[i])
+		apiOrgs[i] = convert.ToOrganization(u.Orgs[i])
 	}
 	c.JSONSuccess(&apiOrgs)
 }
@@ -65,7 +65,7 @@ func CreateMyOrg(c *context.APIContext, apiForm api.CreateOrgOption) {
 }
 
 func ListUserOrgs(c *context.APIContext) {
-	u := user2.GetUserByParams(c)
+	u := user.GetUserByParams(c)
 	if c.Written() {
 		return
 	}
@@ -73,7 +73,7 @@ func ListUserOrgs(c *context.APIContext) {
 }
 
 func Get(c *context.APIContext) {
-	c.JSONSuccess(convert2.ToOrganization(c.Org.Organization))
+	c.JSONSuccess(convert.ToOrganization(c.Org.Organization))
 }
 
 func Edit(c *context.APIContext, form api.EditOrgOption) {
@@ -88,9 +88,9 @@ func Edit(c *context.APIContext, form api.EditOrgOption) {
 	org.Website = form.Website
 	org.Location = form.Location
 	if err := db.UpdateUser(org); err != nil {
-		c.ServerError("UpdateUser", err)
+		c.Error(err, "update user")
 		return
 	}
 
-	c.JSONSuccess(convert2.ToOrganization(org))
+	c.JSONSuccess(convert.ToOrganization(org))
 }

+ 4 - 4
internal/route/api/v1/org/team.go

@@ -6,21 +6,21 @@ package org
 
 import (
 	api "github.com/gogs/go-gogs-client"
-	convert2 "gogs.io/gogs/internal/route/api/v1/convert"
 
 	"gogs.io/gogs/internal/context"
+	"gogs.io/gogs/internal/route/api/v1/convert"
 )
 
 func ListTeams(c *context.APIContext) {
 	org := c.Org.Organization
 	if err := org.GetTeams(); err != nil {
-		c.Error(500, "GetTeams", err)
+		c.Error(err, "get teams")
 		return
 	}
 
 	apiTeams := make([]*api.Team, len(org.Teams))
 	for i := range org.Teams {
-		apiTeams[i] = convert2.ToTeam(org.Teams[i])
+		apiTeams[i] = convert.ToTeam(org.Teams[i])
 	}
-	c.JSON(200, apiTeams)
+	c.JSONSuccess(apiTeams)
 }

+ 8 - 13
internal/route/api/v1/repo/branch.go

@@ -6,38 +6,33 @@ package repo
 
 import (
 	api "github.com/gogs/go-gogs-client"
-	convert2 "gogs.io/gogs/internal/route/api/v1/convert"
 
 	"gogs.io/gogs/internal/context"
-	"gogs.io/gogs/internal/db/errors"
+	"gogs.io/gogs/internal/route/api/v1/convert"
 )
 
 // https://github.com/gogs/go-gogs-client/wiki/Repositories#get-branch
 func GetBranch(c *context.APIContext) {
 	branch, err := c.Repo.Repository.GetBranch(c.Params("*"))
 	if err != nil {
-		if errors.IsErrBranchNotExist(err) {
-			c.Error(404, "GetBranch", err)
-		} else {
-			c.Error(500, "GetBranch", err)
-		}
+		c.NotFoundOrError(err, "get branch")
 		return
 	}
 
 	commit, err := branch.GetCommit()
 	if err != nil {
-		c.Error(500, "GetCommit", err)
+		c.Error(err, "get commit")
 		return
 	}
 
-	c.JSON(200, convert2.ToBranch(branch, commit))
+	c.JSONSuccess( convert.ToBranch(branch, commit))
 }
 
 // https://github.com/gogs/go-gogs-client/wiki/Repositories#list-branches
 func ListBranches(c *context.APIContext) {
 	branches, err := c.Repo.Repository.GetBranches()
 	if err != nil {
-		c.Error(500, "GetBranches", err)
+		c.Error(err, "get branches")
 		return
 	}
 
@@ -45,11 +40,11 @@ func ListBranches(c *context.APIContext) {
 	for i := range branches {
 		commit, err := branches[i].GetCommit()
 		if err != nil {
-			c.Error(500, "GetCommit", err)
+			c.Error(err, "get commit")
 			return
 		}
-		apiBranches[i] = convert2.ToBranch(branches[i], commit)
+		apiBranches[i] = convert.ToBranch(branches[i], commit)
 	}
 
-	c.JSON(200, &apiBranches)
+	c.JSONSuccess( &apiBranches)
 }

+ 19 - 18
internal/route/api/v1/repo/collaborators.go

@@ -5,17 +5,18 @@
 package repo
 
 import (
+	"net/http"
+
 	api "github.com/gogs/go-gogs-client"
 
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
 )
 
 func ListCollaborators(c *context.APIContext) {
 	collaborators, err := c.Repo.Repository.GetCollaborators()
 	if err != nil {
-		c.ServerError("GetCollaborators", err)
+		c.Error(err, "get collaborators")
 		return
 	}
 
@@ -29,62 +30,62 @@ func ListCollaborators(c *context.APIContext) {
 func AddCollaborator(c *context.APIContext, form api.AddCollaboratorOption) {
 	collaborator, err := db.GetUserByName(c.Params(":collaborator"))
 	if err != nil {
-		if errors.IsUserNotExist(err) {
-			c.Error(422, "", err)
+		if db.IsErrUserNotExist(err) {
+			c.Status(http.StatusUnprocessableEntity)
 		} else {
-			c.Error(500, "GetUserByName", err)
+			c.Error(err, "get user by name")
 		}
 		return
 	}
 
 	if err := c.Repo.Repository.AddCollaborator(collaborator); err != nil {
-		c.Error(500, "AddCollaborator", err)
+		c.Error(err, "add collaborator")
 		return
 	}
 
 	if form.Permission != nil {
 		if err := c.Repo.Repository.ChangeCollaborationAccessMode(collaborator.ID, db.ParseAccessMode(*form.Permission)); err != nil {
-			c.Error(500, "ChangeCollaborationAccessMode", err)
+			c.Error(err, "change collaboration access mode")
 			return
 		}
 	}
 
-	c.Status(204)
+	c.NoContent()
 }
 
 func IsCollaborator(c *context.APIContext) {
 	collaborator, err := db.GetUserByName(c.Params(":collaborator"))
 	if err != nil {
-		if errors.IsUserNotExist(err) {
-			c.Error(422, "", err)
+		if db.IsErrUserNotExist(err) {
+			c.Status(http.StatusUnprocessableEntity)
 		} else {
-			c.Error(500, "GetUserByName", err)
+			c.Error(err, "get user by name")
 		}
 		return
 	}
 
 	if !c.Repo.Repository.IsCollaborator(collaborator.ID) {
-		c.Status(404)
+		c.NotFound()
 	} else {
-		c.Status(204)
+		c.NoContent()
 	}
 }
 
 func DeleteCollaborator(c *context.APIContext) {
 	collaborator, err := db.GetUserByName(c.Params(":collaborator"))
 	if err != nil {
-		if errors.IsUserNotExist(err) {
-			c.Error(422, "", err)
+		if db.IsErrUserNotExist(err) {
+			c.Status(http.StatusUnprocessableEntity)
 		} else {
-			c.Error(500, "GetUserByName", err)
+			c.Error(err, "get user by name")
 		}
 		return
 	}
 
 	if err := c.Repo.Repository.DeleteCollaboration(collaborator.ID); err != nil {
-		c.Error(500, "DeleteCollaboration", err)
+		c.Error(err, "delete collaboration")
 		return
 	}
 
-	c.Status(204)
+	c.NoContent()
 }

+ 9 - 10
internal/route/api/v1/repo/commits.go

@@ -15,7 +15,6 @@ import (
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
 	"gogs.io/gogs/internal/gitutil"
 )
 
@@ -28,20 +27,20 @@ func GetSingleCommit(c *context.APIContext) {
 
 	gitRepo, err := git.Open(c.Repo.Repository.RepoPath())
 	if err != nil {
-		c.ServerError("open repository", err)
+		c.Error(err, "open repository")
 		return
 	}
 	commit, err := gitRepo.CatFileCommit(c.Params(":sha"))
 	if err != nil {
-		c.NotFoundOrServerError("get commit", gitutil.IsErrRevisionNotExist, err)
+		c.NotFoundOrError(gitutil.NewError(err), "get commit")
 		return
 	}
 
 	// Retrieve author and committer information
 	var apiAuthor, apiCommitter *api.User
 	author, err := db.GetUserByEmail(commit.Author.Email)
-	if err != nil && !errors.IsUserNotExist(err) {
-		c.ServerError("Get user by author email", err)
+	if err != nil && !db.IsErrUserNotExist(err) {
+		c.Error(err, "get user by author email")
 		return
 	} else if err == nil {
 		apiAuthor = author.APIFormat()
@@ -51,8 +50,8 @@ func GetSingleCommit(c *context.APIContext) {
 		apiCommitter = apiAuthor
 	} else {
 		committer, err := db.GetUserByEmail(commit.Committer.Email)
-		if err != nil && !errors.IsUserNotExist(err) {
-			c.ServerError("Get user by committer email", err)
+		if err != nil && !db.IsErrUserNotExist(err) {
+			c.Error(err, "get user by committer email")
 			return
 		} else if err == nil {
 			apiCommitter = committer.APIFormat()
@@ -102,7 +101,7 @@ func GetSingleCommit(c *context.APIContext) {
 func GetReferenceSHA(c *context.APIContext) {
 	gitRepo, err := git.Open(c.Repo.Repository.RepoPath())
 	if err != nil {
-		c.ServerError("open repository", err)
+		c.Error(err, "open repository")
 		return
 	}
 
@@ -132,8 +131,8 @@ func GetReferenceSHA(c *context.APIContext) {
 		sha, err = gitRepo.TagCommitID(ref)
 	}
 	if err != nil {
-		c.NotFoundOrServerError("get reference commit ID", gitutil.IsErrRevisionNotExist, err)
+		c.NotFoundOrError(gitutil.NewError(err), "get reference commit ID")
 		return
 	}
-	c.PlainText(http.StatusOK, []byte(sha))
+	c.PlainText(http.StatusOK, sha)
 }

+ 5 - 5
internal/route/api/v1/repo/contents.go

@@ -19,7 +19,7 @@ import (
 func GetContents(c *context.APIContext) {
 	gitRepo, err := git.Open(c.Repo.Repository.RepoPath())
 	if err != nil {
-		c.ServerError("open repository", err)
+		c.Error(err, "open repository")
 		return
 	}
 
@@ -30,14 +30,14 @@ func GetContents(c *context.APIContext) {
 
 	commit, err := gitRepo.CatFileCommit(ref)
 	if err != nil {
-		c.NotFoundOrServerError("get commit", gitutil.IsErrRevisionNotExist, err)
+		c.NotFoundOrError(gitutil.NewError(err), "get commit")
 		return
 	}
 
 	treePath := c.Params("*")
 	entry, err := commit.TreeEntry(treePath)
 	if err != nil {
-		c.NotFoundOrServerError("get tree entry", gitutil.IsErrRevisionNotExist, err)
+		c.NotFoundOrError(gitutil.NewError(err), "get tree entry")
 		return
 	}
 
@@ -137,13 +137,13 @@ func GetContents(c *context.APIContext) {
 	// The entry is a directory
 	dir, err := gitRepo.LsTree(entry.ID().String())
 	if err != nil {
-		c.NotFoundOrServerError("get tree", gitutil.IsErrRevisionNotExist, err)
+		c.NotFoundOrError(gitutil.NewError(err), "get tree")
 		return
 	}
 
 	entries, err := dir.Entries()
 	if err != nil {
-		c.NotFoundOrServerError("list entries", gitutil.IsErrRevisionNotExist, err)
+		c.NotFoundOrError(gitutil.NewError(err), "list entries")
 		return
 	}
 

+ 5 - 5
internal/route/api/v1/repo/file.go

@@ -26,11 +26,11 @@ func GetRawFile(c *context.APIContext) {
 
 	blob, err := c.Repo.Commit.Blob(c.Repo.TreePath)
 	if err != nil {
-		c.NotFoundOrServerError("get blob", gitutil.IsErrRevisionNotExist, err)
+		c.NotFoundOrError(gitutil.NewError(err), "get blob")
 		return
 	}
 	if err = repo.ServeBlob(c.Context, blob); err != nil {
-		c.ServerError("ServeBlob", err)
+		c.Error(err, "serve blob")
 	}
 }
 
@@ -38,7 +38,7 @@ func GetArchive(c *context.APIContext) {
 	repoPath := db.RepoPath(c.Params(":username"), c.Params(":reponame"))
 	gitRepo, err := git.Open(repoPath)
 	if err != nil {
-		c.ServerError("open repository", err)
+		c.Error(err, "open repository")
 		return
 	}
 	c.Repo.GitRepo = gitRepo
@@ -49,14 +49,14 @@ func GetArchive(c *context.APIContext) {
 func GetEditorconfig(c *context.APIContext) {
 	ec, err := c.Repo.Editorconfig()
 	if err != nil {
-		c.NotFoundOrServerError("get .editorconfig", gitutil.IsErrRevisionNotExist, err)
+		c.NotFoundOrError(gitutil.NewError(err), "get .editorconfig")
 		return
 	}
 
 	fileName := c.Params("filename")
 	def, err := ec.GetDefinitionForFilename(fileName)
 	if err != nil {
-		c.ServerError("get definition for filename", err)
+		c.Error(err, "get definition for filename")
 		return
 	}
 	if def == nil {

+ 24 - 27
internal/route/api/v1/repo/hook.go

@@ -5,46 +5,47 @@
 package repo
 
 import (
-	"github.com/json-iterator/go"
-	"github.com/unknwon/com"
-	convert2 "gogs.io/gogs/internal/route/api/v1/convert"
+	"net/http"
 
 	api "github.com/gogs/go-gogs-client"
+	"github.com/json-iterator/go"
+	"github.com/pkg/errors"
+	"github.com/unknwon/com"
 
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
+	"gogs.io/gogs/internal/route/api/v1/convert"
 )
 
 // https://github.com/gogs/go-gogs-client/wiki/Repositories#list-hooks
 func ListHooks(c *context.APIContext) {
 	hooks, err := db.GetWebhooksByRepoID(c.Repo.Repository.ID)
 	if err != nil {
-		c.Error(500, "GetWebhooksByRepoID", err)
+		c.Errorf(err, "get webhooks by repository ID")
 		return
 	}
 
 	apiHooks := make([]*api.Hook, len(hooks))
 	for i := range hooks {
-		apiHooks[i] = convert2.ToHook(c.Repo.RepoLink, hooks[i])
+		apiHooks[i] = convert.ToHook(c.Repo.RepoLink, hooks[i])
 	}
-	c.JSON(200, &apiHooks)
+	c.JSONSuccess(&apiHooks)
 }
 
 // https://github.com/gogs/go-gogs-client/wiki/Repositories#create-a-hook
 func CreateHook(c *context.APIContext, form api.CreateHookOption) {
 	if !db.IsValidHookTaskType(form.Type) {
-		c.Error(422, "", "Invalid hook type")
+		c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Invalid hook type."))
 		return
 	}
 	for _, name := range []string{"url", "content_type"} {
 		if _, ok := form.Config[name]; !ok {
-			c.Error(422, "", "Missing config option: "+name)
+			c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Missing config option: "+name))
 			return
 		}
 	}
 	if !db.IsValidHookContentType(form.Config["content_type"]) {
-		c.Error(422, "", "Invalid content type")
+		c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Invalid content type."))
 		return
 	}
 
@@ -75,7 +76,7 @@ func CreateHook(c *context.APIContext, form api.CreateHookOption) {
 	if w.HookTaskType == db.SLACK {
 		channel, ok := form.Config["channel"]
 		if !ok {
-			c.Error(422, "", "Missing config option: channel")
+			c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Missing config option: channel"))
 			return
 		}
 		meta, err := jsoniter.Marshal(&db.SlackMeta{
@@ -85,32 +86,28 @@ func CreateHook(c *context.APIContext, form api.CreateHookOption) {
 			Color:    form.Config["color"],
 		})
 		if err != nil {
-			c.Error(500, "slack: JSON marshal failed", err)
+			c.Errorf(err, "marshal JSON")
 			return
 		}
 		w.Meta = string(meta)
 	}
 
 	if err := w.UpdateEvent(); err != nil {
-		c.Error(500, "UpdateEvent", err)
+		c.Errorf(err, "update event")
 		return
 	} else if err := db.CreateWebhook(w); err != nil {
-		c.Error(500, "CreateWebhook", err)
+		c.Errorf(err, "create webhook")
 		return
 	}
 
-	c.JSON(201, convert2.ToHook(c.Repo.RepoLink, w))
+	c.JSON(http.StatusCreated, convert.ToHook(c.Repo.RepoLink, w))
 }
 
 // https://github.com/gogs/go-gogs-client/wiki/Repositories#edit-a-hook
 func EditHook(c *context.APIContext, form api.EditHookOption) {
 	w, err := db.GetWebhookOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
 	if err != nil {
-		if errors.IsWebhookNotExist(err) {
-			c.Status(404)
-		} else {
-			c.Error(500, "GetWebhookOfRepoByID", err)
-		}
+		c.NotFoundOrError(err, "get webhook of repository by ID")
 		return
 	}
 
@@ -120,7 +117,7 @@ func EditHook(c *context.APIContext, form api.EditHookOption) {
 		}
 		if ct, ok := form.Config["content_type"]; ok {
 			if !db.IsValidHookContentType(ct) {
-				c.Error(422, "", "Invalid content type")
+				c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Invalid content type."))
 				return
 			}
 			w.ContentType = db.ToHookContentType(ct)
@@ -135,7 +132,7 @@ func EditHook(c *context.APIContext, form api.EditHookOption) {
 					Color:    form.Config["color"],
 				})
 				if err != nil {
-					c.Error(500, "slack: JSON marshal failed", err)
+					c.Errorf(err, "marshal JSON")
 					return
 				}
 				w.Meta = string(meta)
@@ -159,7 +156,7 @@ func EditHook(c *context.APIContext, form api.EditHookOption) {
 	w.PullRequest = com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_PULL_REQUEST))
 	w.Release = com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_RELEASE))
 	if err = w.UpdateEvent(); err != nil {
-		c.Error(500, "UpdateEvent", err)
+		c.Errorf(err, "update event")
 		return
 	}
 
@@ -168,18 +165,18 @@ func EditHook(c *context.APIContext, form api.EditHookOption) {
 	}
 
 	if err := db.UpdateWebhook(w); err != nil {
-		c.Error(500, "UpdateWebhook", err)
+		c.Errorf(err, "update webhook")
 		return
 	}
 
-	c.JSON(200, convert2.ToHook(c.Repo.RepoLink, w))
+	c.JSONSuccess(convert.ToHook(c.Repo.RepoLink, w))
 }
 
 func DeleteHook(c *context.APIContext) {
 	if err := db.DeleteWebhookOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id")); err != nil {
-		c.Error(500, "DeleteWebhookByRepoID", err)
+		c.Errorf(err, "delete webhook of repository by ID")
 		return
 	}
 
-	c.Status(204)
+	c.NoContent()
 }

+ 20 - 21
internal/route/api/v1/repo/issue.go

@@ -11,22 +11,21 @@ import (
 
 	api "github.com/gogs/go-gogs-client"
 
+	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
-	"gogs.io/gogs/internal/conf"
 )
 
 func listIssues(c *context.APIContext, opts *db.IssuesOptions) {
 	issues, err := db.Issues(opts)
 	if err != nil {
-		c.ServerError("Issues", err)
+		c.Error(err, "list issues")
 		return
 	}
 
 	count, err := db.IssuesCount(opts)
 	if err != nil {
-		c.ServerError("IssuesCount", err)
+		c.Error(err, "count issues")
 		return
 	}
 
@@ -34,7 +33,7 @@ func listIssues(c *context.APIContext, opts *db.IssuesOptions) {
 	apiIssues := make([]*api.Issue, len(issues))
 	for i := range issues {
 		if err = issues[i].LoadAttributes(); err != nil {
-			c.ServerError("LoadAttributes", err)
+			c.Error(err, "load attributes")
 			return
 		}
 		apiIssues[i] = issues[i].APIFormat()
@@ -67,7 +66,7 @@ func ListIssues(c *context.APIContext) {
 func GetIssue(c *context.APIContext) {
 	issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
 	if err != nil {
-		c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
+		c.NotFoundOrError(err, "get issue by index")
 		return
 	}
 	c.JSONSuccess(issue.APIFormat())
@@ -86,10 +85,10 @@ func CreateIssue(c *context.APIContext, form api.CreateIssueOption) {
 		if len(form.Assignee) > 0 {
 			assignee, err := db.GetUserByName(form.Assignee)
 			if err != nil {
-				if errors.IsUserNotExist(err) {
-					c.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("assignee does not exist: [name: %s]", form.Assignee))
+				if db.IsErrUserNotExist(err) {
+					c.ErrorStatus(http.StatusUnprocessableEntity, fmt.Errorf("assignee does not exist: [name: %s]", form.Assignee))
 				} else {
-					c.ServerError("GetUserByName", err)
+					c.Error(err, "get user by name")
 				}
 				return
 			}
@@ -101,13 +100,13 @@ func CreateIssue(c *context.APIContext, form api.CreateIssueOption) {
 	}
 
 	if err := db.NewIssue(c.Repo.Repository, issue, form.Labels, nil); err != nil {
-		c.ServerError("NewIssue", err)
+		c.Error(err, "new issue")
 		return
 	}
 
 	if form.Closed {
 		if err := issue.ChangeStatus(c.User, c.Repo.Repository, true); err != nil {
-			c.ServerError("ChangeStatus", err)
+			c.Error(err, "change status to closed")
 			return
 		}
 	}
@@ -116,7 +115,7 @@ func CreateIssue(c *context.APIContext, form api.CreateIssueOption) {
 	var err error
 	issue, err = db.GetIssueByID(issue.ID)
 	if err != nil {
-		c.ServerError("GetIssueByID", err)
+		c.Error(err, "get issue by ID")
 		return
 	}
 	c.JSON(http.StatusCreated, issue.APIFormat())
@@ -125,7 +124,7 @@ func CreateIssue(c *context.APIContext, form api.CreateIssueOption) {
 func EditIssue(c *context.APIContext, form api.EditIssueOption) {
 	issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
 	if err != nil {
-		c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
+		c.NotFoundOrError(err, "get issue by index")
 		return
 	}
 
@@ -148,10 +147,10 @@ func EditIssue(c *context.APIContext, form api.EditIssueOption) {
 		} else {
 			assignee, err := db.GetUserByName(*form.Assignee)
 			if err != nil {
-				if errors.IsUserNotExist(err) {
-					c.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("assignee does not exist: [name: %s]", *form.Assignee))
+				if db.IsErrUserNotExist(err) {
+					c.ErrorStatus(http.StatusUnprocessableEntity, fmt.Errorf("assignee does not exist: [name: %s]", *form.Assignee))
 				} else {
-					c.ServerError("GetUserByName", err)
+					c.Error(err, "get user by name")
 				}
 				return
 			}
@@ -159,7 +158,7 @@ func EditIssue(c *context.APIContext, form api.EditIssueOption) {
 		}
 
 		if err = db.UpdateIssueUserByAssignee(issue); err != nil {
-			c.ServerError("UpdateIssueUserByAssignee", err)
+			c.Error(err, "update issue user by assignee")
 			return
 		}
 	}
@@ -168,18 +167,18 @@ func EditIssue(c *context.APIContext, form api.EditIssueOption) {
 		oldMilestoneID := issue.MilestoneID
 		issue.MilestoneID = *form.Milestone
 		if err = db.ChangeMilestoneAssign(c.User, issue, oldMilestoneID); err != nil {
-			c.ServerError("ChangeMilestoneAssign", err)
+			c.Error(err, "change milestone assign")
 			return
 		}
 	}
 
 	if err = db.UpdateIssue(issue); err != nil {
-		c.ServerError("UpdateIssue", err)
+		c.Error(err, "update issue")
 		return
 	}
 	if form.State != nil {
 		if err = issue.ChangeStatus(c.User, c.Repo.Repository, api.STATE_CLOSED == api.StateType(*form.State)); err != nil {
-			c.ServerError("ChangeStatus", err)
+			c.Error(err, "change status")
 			return
 		}
 	}
@@ -187,7 +186,7 @@ func EditIssue(c *context.APIContext, form api.EditIssueOption) {
 	// Refetch from database to assign some automatic values
 	issue, err = db.GetIssueByID(issue.ID)
 	if err != nil {
-		c.ServerError("GetIssueByID", err)
+		c.Error(err, "get issue by ID")
 		return
 	}
 	c.JSON(http.StatusCreated, issue.APIFormat())

+ 11 - 11
internal/route/api/v1/repo/issue_comment.go

@@ -19,7 +19,7 @@ func ListIssueComments(c *context.APIContext) {
 		var err error
 		since, err = time.Parse(time.RFC3339, c.Query("since"))
 		if err != nil {
-			c.Error(http.StatusUnprocessableEntity, "", err)
+			c.ErrorStatus(http.StatusUnprocessableEntity, err)
 			return
 		}
 	}
@@ -27,13 +27,13 @@ func ListIssueComments(c *context.APIContext) {
 	// comments,err:=db.GetCommentsByIssueIDSince(, since)
 	issue, err := db.GetRawIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
 	if err != nil {
-		c.ServerError("GetRawIssueByIndex", err)
+		c.Error(err, "get raw issue by index")
 		return
 	}
 
 	comments, err := db.GetCommentsByIssueIDSince(issue.ID, since.Unix())
 	if err != nil {
-		c.ServerError("GetCommentsByIssueIDSince", err)
+		c.Error(err, "get comments by issue ID")
 		return
 	}
 
@@ -50,14 +50,14 @@ func ListRepoIssueComments(c *context.APIContext) {
 		var err error
 		since, err = time.Parse(time.RFC3339, c.Query("since"))
 		if err != nil {
-			c.Error(http.StatusUnprocessableEntity, "", err)
+			c.ErrorStatus(http.StatusUnprocessableEntity, err)
 			return
 		}
 	}
 
 	comments, err := db.GetCommentsByRepoIDSince(c.Repo.Repository.ID, since.Unix())
 	if err != nil {
-		c.ServerError("GetCommentsByRepoIDSince", err)
+		c.Error(err, "get comments by repository ID")
 		return
 	}
 
@@ -71,13 +71,13 @@ func ListRepoIssueComments(c *context.APIContext) {
 func CreateIssueComment(c *context.APIContext, form api.CreateIssueCommentOption) {
 	issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
 	if err != nil {
-		c.ServerError("GetIssueByIndex", err)
+		c.Error(err, "get issue by index")
 		return
 	}
 
 	comment, err := db.CreateIssueComment(c.User, c.Repo.Repository, issue, form.Body, nil)
 	if err != nil {
-		c.ServerError("CreateIssueComment", err)
+		c.Error(err, "create issue comment")
 		return
 	}
 
@@ -87,7 +87,7 @@ func CreateIssueComment(c *context.APIContext, form api.CreateIssueCommentOption
 func EditIssueComment(c *context.APIContext, form api.EditIssueCommentOption) {
 	comment, err := db.GetCommentByID(c.ParamsInt64(":id"))
 	if err != nil {
-		c.NotFoundOrServerError("GetCommentByID", db.IsErrCommentNotExist, err)
+		c.NotFoundOrError(err, "get comment by ID")
 		return
 	}
 
@@ -102,7 +102,7 @@ func EditIssueComment(c *context.APIContext, form api.EditIssueCommentOption) {
 	oldContent := comment.Content
 	comment.Content = form.Body
 	if err := db.UpdateComment(c.User, comment, oldContent); err != nil {
-		c.ServerError("UpdateComment", err)
+		c.Error(err, "update comment")
 		return
 	}
 	c.JSONSuccess(comment.APIFormat())
@@ -111,7 +111,7 @@ func EditIssueComment(c *context.APIContext, form api.EditIssueCommentOption) {
 func DeleteIssueComment(c *context.APIContext) {
 	comment, err := db.GetCommentByID(c.ParamsInt64(":id"))
 	if err != nil {
-		c.NotFoundOrServerError("GetCommentByID", db.IsErrCommentNotExist, err)
+		c.NotFoundOrError(err, "get comment by ID")
 		return
 	}
 
@@ -124,7 +124,7 @@ func DeleteIssueComment(c *context.APIContext) {
 	}
 
 	if err = db.DeleteCommentByID(c.User, comment.ID); err != nil {
-		c.ServerError("DeleteCommentByID", err)
+		c.Error(err, "delete comment by ID")
 		return
 	}
 	c.NoContent()

+ 15 - 16
internal/route/api/v1/repo/issue_label.go

@@ -11,13 +11,12 @@ import (
 
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
 )
 
 func ListIssueLabels(c *context.APIContext) {
 	issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
 	if err != nil {
-		c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
+		c.NotFoundOrError(err, "get issue by index")
 		return
 	}
 
@@ -31,24 +30,24 @@ func ListIssueLabels(c *context.APIContext) {
 func AddIssueLabels(c *context.APIContext, form api.IssueLabelsOption) {
 	issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
 	if err != nil {
-		c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
+		c.NotFoundOrError(err, "get issue by index")
 		return
 	}
 
 	labels, err := db.GetLabelsInRepoByIDs(c.Repo.Repository.ID, form.Labels)
 	if err != nil {
-		c.ServerError("GetLabelsInRepoByIDs", err)
+		c.Error(err, "get labels in repository by IDs")
 		return
 	}
 
 	if err = issue.AddLabels(c.User, labels); err != nil {
-		c.ServerError("AddLabels", err)
+		c.Error(err, "add labels")
 		return
 	}
 
 	labels, err = db.GetLabelsByIssueID(issue.ID)
 	if err != nil {
-		c.ServerError("GetLabelsByIssueID", err)
+		c.Error(err, "get labels by issue ID")
 		return
 	}
 
@@ -62,22 +61,22 @@ func AddIssueLabels(c *context.APIContext, form api.IssueLabelsOption) {
 func DeleteIssueLabel(c *context.APIContext) {
 	issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
 	if err != nil {
-		c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
+		c.NotFoundOrError(err, "get issue by index")
 		return
 	}
 
 	label, err := db.GetLabelOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
 	if err != nil {
 		if db.IsErrLabelNotExist(err) {
-			c.Error(http.StatusUnprocessableEntity, "", err)
+			c.ErrorStatus(http.StatusUnprocessableEntity, err)
 		} else {
-			c.ServerError("GetLabelInRepoByID", err)
+			c.Error(err, "get label of repository by ID")
 		}
 		return
 	}
 
 	if err := db.DeleteIssueLabel(issue, label); err != nil {
-		c.ServerError("DeleteIssueLabel", err)
+		c.Error(err, "delete issue label")
 		return
 	}
 
@@ -87,24 +86,24 @@ func DeleteIssueLabel(c *context.APIContext) {
 func ReplaceIssueLabels(c *context.APIContext, form api.IssueLabelsOption) {
 	issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
 	if err != nil {
-		c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
+		c.NotFoundOrError(err, "get issue by index")
 		return
 	}
 
 	labels, err := db.GetLabelsInRepoByIDs(c.Repo.Repository.ID, form.Labels)
 	if err != nil {
-		c.ServerError("GetLabelsInRepoByIDs", err)
+		c.Error(err, "get labels in repository by IDs")
 		return
 	}
 
 	if err := issue.ReplaceLabels(labels); err != nil {
-		c.ServerError("ReplaceLabels", err)
+		c.Error(err, "replace labels")
 		return
 	}
 
 	labels, err = db.GetLabelsByIssueID(issue.ID)
 	if err != nil {
-		c.ServerError("GetLabelsByIssueID", err)
+		c.Error(err, "get labels by issue ID")
 		return
 	}
 
@@ -118,12 +117,12 @@ func ReplaceIssueLabels(c *context.APIContext, form api.IssueLabelsOption) {
 func ClearIssueLabels(c *context.APIContext) {
 	issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
 	if err != nil {
-		c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
+		c.NotFoundOrError(err, "get issue by index")
 		return
 	}
 
 	if err := issue.ClearLabels(c.User); err != nil {
-		c.ServerError("ClearLabels", err)
+		c.Error(err, "clear labels")
 		return
 	}
 

+ 19 - 22
internal/route/api/v1/repo/key.go

@@ -5,14 +5,15 @@
 package repo
 
 import (
-	"fmt"
-	convert2 "gogs.io/gogs/internal/route/api/v1/convert"
+	"net/http"
 
 	api "github.com/gogs/go-gogs-client"
+	"github.com/pkg/errors"
 
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
+	"gogs.io/gogs/internal/route/api/v1/convert"
 )
 
 func composeDeployKeysAPILink(repoPath string) string {
@@ -23,7 +24,7 @@ func composeDeployKeysAPILink(repoPath string) string {
 func ListDeployKeys(c *context.APIContext) {
 	keys, err := db.ListDeployKeys(c.Repo.Repository.ID)
 	if err != nil {
-		c.Error(500, "ListDeployKeys", err)
+		c.Error(err, "list deploy keys")
 		return
 	}
 
@@ -31,52 +32,48 @@ func ListDeployKeys(c *context.APIContext) {
 	apiKeys := make([]*api.DeployKey, len(keys))
 	for i := range keys {
 		if err = keys[i].GetContent(); err != nil {
-			c.Error(500, "GetContent", err)
+			c.Error(err, "get content")
 			return
 		}
-		apiKeys[i] = convert2.ToDeployKey(apiLink, keys[i])
+		apiKeys[i] = convert.ToDeployKey(apiLink, keys[i])
 	}
 
-	c.JSON(200, &apiKeys)
+	c.JSONSuccess(&apiKeys)
 }
 
 // https://github.com/gogs/go-gogs-client/wiki/Repositories-Deploy-Keys#get-a-deploy-key
 func GetDeployKey(c *context.APIContext) {
 	key, err := db.GetDeployKeyByID(c.ParamsInt64(":id"))
 	if err != nil {
-		if db.IsErrDeployKeyNotExist(err) {
-			c.Status(404)
-		} else {
-			c.Error(500, "GetDeployKeyByID", err)
-		}
+		c.NotFoundOrError(err, "get deploy key by ID")
 		return
 	}
 
 	if err = key.GetContent(); err != nil {
-		c.Error(500, "GetContent", err)
+		c.Error(err, "get content")
 		return
 	}
 
 	apiLink := composeDeployKeysAPILink(c.Repo.Owner.Name + "/" + c.Repo.Repository.Name)
-	c.JSON(200, convert2.ToDeployKey(apiLink, key))
+	c.JSONSuccess(convert.ToDeployKey(apiLink, key))
 }
 
 func HandleCheckKeyStringError(c *context.APIContext, err error) {
 	if db.IsErrKeyUnableVerify(err) {
-		c.Error(422, "", "Unable to verify key content")
+		c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Unable to verify key content"))
 	} else {
-		c.Error(422, "", fmt.Errorf("Invalid key content: %v", err))
+		c.ErrorStatus(http.StatusUnprocessableEntity, errors.Wrap(err, "Invalid key content: %v"))
 	}
 }
 
 func HandleAddKeyError(c *context.APIContext, err error) {
 	switch {
 	case db.IsErrKeyAlreadyExist(err):
-		c.Error(422, "", "Key content has been used as non-deploy key")
+		c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Key content has been used as non-deploy key"))
 	case db.IsErrKeyNameAlreadyUsed(err):
-		c.Error(422, "", "Key title has been used")
+		c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Key title has been used"))
 	default:
-		c.Error(500, "AddKey", err)
+		c.Error(err, "add key")
 	}
 }
 
@@ -96,19 +93,19 @@ func CreateDeployKey(c *context.APIContext, form api.CreateKeyOption) {
 
 	key.Content = content
 	apiLink := composeDeployKeysAPILink(c.Repo.Owner.Name + "/" + c.Repo.Repository.Name)
-	c.JSON(201, convert2.ToDeployKey(apiLink, key))
+	c.JSON(http.StatusCreated, convert.ToDeployKey(apiLink, key))
 }
 
 // https://github.com/gogs/go-gogs-client/wiki/Repositories-Deploy-Keys#remove-a-deploy-key
 func DeleteDeploykey(c *context.APIContext) {
 	if err := db.DeleteDeployKey(c.User, c.ParamsInt64(":id")); err != nil {
 		if db.IsErrKeyAccessDenied(err) {
-			c.Error(403, "", "You do not have access to this key")
+			c.ErrorStatus(http.StatusForbidden, errors.New("You do not have access to this key"))
 		} else {
-			c.Error(500, "DeleteDeployKey", err)
+			c.Error(err, "delete deploy key")
 		}
 		return
 	}
 
-	c.Status(204)
+	c.NoContent()
 }

+ 7 - 8
internal/route/api/v1/repo/label.go

@@ -7,9 +7,8 @@ package repo
 import (
 	"net/http"
 
-	"github.com/unknwon/com"
-
 	api "github.com/gogs/go-gogs-client"
+	"github.com/unknwon/com"
 
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
@@ -18,7 +17,7 @@ import (
 func ListLabels(c *context.APIContext) {
 	labels, err := db.GetLabelsByRepoID(c.Repo.Repository.ID)
 	if err != nil {
-		c.ServerError("GetLabelsByRepoID", err)
+		c.Error(err, "get labels by repository ID")
 		return
 	}
 
@@ -39,7 +38,7 @@ func GetLabel(c *context.APIContext) {
 		label, err = db.GetLabelOfRepoByName(c.Repo.Repository.ID, idStr)
 	}
 	if err != nil {
-		c.NotFoundOrServerError("GetLabel", db.IsErrLabelNotExist, err)
+		c.NotFoundOrError(err, "get label")
 		return
 	}
 
@@ -53,7 +52,7 @@ func CreateLabel(c *context.APIContext, form api.CreateLabelOption) {
 		RepoID: c.Repo.Repository.ID,
 	}
 	if err := db.NewLabels(label); err != nil {
-		c.ServerError("NewLabel", err)
+		c.Error(err, "new labels")
 		return
 	}
 	c.JSON(http.StatusCreated, label.APIFormat())
@@ -62,7 +61,7 @@ func CreateLabel(c *context.APIContext, form api.CreateLabelOption) {
 func EditLabel(c *context.APIContext, form api.EditLabelOption) {
 	label, err := db.GetLabelOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
 	if err != nil {
-		c.NotFoundOrServerError("GetLabelOfRepoByID", db.IsErrLabelNotExist, err)
+		c.NotFoundOrError(err, "get label of repository by ID")
 		return
 	}
 
@@ -73,7 +72,7 @@ func EditLabel(c *context.APIContext, form api.EditLabelOption) {
 		label.Color = *form.Color
 	}
 	if err := db.UpdateLabel(label); err != nil {
-		c.ServerError("UpdateLabel", err)
+		c.Error(err, "update label")
 		return
 	}
 	c.JSONSuccess(label.APIFormat())
@@ -81,7 +80,7 @@ func EditLabel(c *context.APIContext, form api.EditLabelOption) {
 
 func DeleteLabel(c *context.APIContext) {
 	if err := db.DeleteLabel(c.Repo.Repository.ID, c.ParamsInt64(":id")); err != nil {
-		c.ServerError("DeleteLabel", err)
+		c.Error(err, "delete label")
 		return
 	}
 

+ 7 - 7
internal/route/api/v1/repo/milestone.go

@@ -17,7 +17,7 @@ import (
 func ListMilestones(c *context.APIContext) {
 	milestones, err := db.GetMilestonesByRepoID(c.Repo.Repository.ID)
 	if err != nil {
-		c.ServerError("GetMilestonesByRepoID", err)
+		c.Error(err, "get milestones by repository ID")
 		return
 	}
 
@@ -31,7 +31,7 @@ func ListMilestones(c *context.APIContext) {
 func GetMilestone(c *context.APIContext) {
 	milestone, err := db.GetMilestoneByRepoID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
 	if err != nil {
-		c.NotFoundOrServerError("GetMilestoneByRepoID", db.IsErrMilestoneNotExist, err)
+		c.NotFoundOrError(err, "get milestone by repository ID")
 		return
 	}
 	c.JSONSuccess(milestone.APIFormat())
@@ -51,7 +51,7 @@ func CreateMilestone(c *context.APIContext, form api.CreateMilestoneOption) {
 	}
 
 	if err := db.NewMilestone(milestone); err != nil {
-		c.ServerError("NewMilestone", err)
+		c.Error(err, "new milestone")
 		return
 	}
 	c.JSON(http.StatusCreated, milestone.APIFormat())
@@ -60,7 +60,7 @@ func CreateMilestone(c *context.APIContext, form api.CreateMilestoneOption) {
 func EditMilestone(c *context.APIContext, form api.EditMilestoneOption) {
 	milestone, err := db.GetMilestoneByRepoID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
 	if err != nil {
-		c.NotFoundOrServerError("GetMilestoneByRepoID", db.IsErrMilestoneNotExist, err)
+		c.NotFoundOrError(err, "get milestone by repository ID")
 		return
 	}
 
@@ -76,11 +76,11 @@ func EditMilestone(c *context.APIContext, form api.EditMilestoneOption) {
 
 	if form.State != nil {
 		if err = milestone.ChangeStatus(api.STATE_CLOSED == api.StateType(*form.State)); err != nil {
-			c.ServerError("ChangeStatus", err)
+			c.Error(err, "change status")
 			return
 		}
 	} else if err = db.UpdateMilestone(milestone); err != nil {
-		c.ServerError("UpdateMilestone", err)
+		c.Error(err, "update milestone")
 		return
 	}
 
@@ -89,7 +89,7 @@ func EditMilestone(c *context.APIContext, form api.EditMilestoneOption) {
 
 func DeleteMilestone(c *context.APIContext) {
 	if err := db.DeleteMilestoneOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id")); err != nil {
-		c.ServerError("DeleteMilestoneByRepoID", err)
+		c.Error(err, "delete milestone of repository by ID")
 		return
 	}
 	c.NoContent()

+ 35 - 37
internal/route/api/v1/repo/repo.go

@@ -5,18 +5,16 @@
 package repo
 
 import (
-	"fmt"
 	"net/http"
 	"path"
 
-	log "unknwon.dev/clog/v2"
-
 	api "github.com/gogs/go-gogs-client"
+	"github.com/pkg/errors"
+	log "unknwon.dev/clog/v2"
 
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
 	"gogs.io/gogs/internal/form"
 	"gogs.io/gogs/internal/route/api/v1/convert"
 )
@@ -81,7 +79,7 @@ func Search(c *context.APIContext) {
 func listUserRepositories(c *context.APIContext, username string) {
 	user, err := db.GetUserByName(username)
 	if err != nil {
-		c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
+		c.NotFoundOrError(err, "get user by name")
 		return
 	}
 
@@ -99,12 +97,12 @@ func listUserRepositories(c *context.APIContext, username string) {
 		})
 	}
 	if err != nil {
-		c.ServerError("GetUserRepositories", err)
+		c.Error(err, "get user repositories")
 		return
 	}
 
 	if err = db.RepositoryList(ownRepos).LoadAttributes(); err != nil {
-		c.ServerError("LoadAttributes(ownRepos)", err)
+		c.Error(err, "load attributes")
 		return
 	}
 
@@ -120,7 +118,7 @@ func listUserRepositories(c *context.APIContext, username string) {
 
 	accessibleRepos, err := user.GetRepositoryAccesses()
 	if err != nil {
-		c.ServerError("GetRepositoryAccesses", err)
+		c.Error(err, "get repositories accesses")
 		return
 	}
 
@@ -169,14 +167,14 @@ func CreateUserRepo(c *context.APIContext, owner *db.User, opt api.CreateRepoOpt
 		if db.IsErrRepoAlreadyExist(err) ||
 			db.IsErrNameReserved(err) ||
 			db.IsErrNamePatternNotAllowed(err) {
-			c.Error(http.StatusUnprocessableEntity, "", err)
+			c.ErrorStatus(http.StatusUnprocessableEntity, err)
 		} else {
 			if repo != nil {
 				if err = db.DeleteRepository(c.User.ID, repo.ID); err != nil {
-					log.Error("DeleteRepository: %v", err)
+					log.Error("Failed to delete repository: %v", err)
 				}
 			}
-			c.ServerError("CreateRepository", err)
+			c.Error(err, "create repository")
 		}
 		return
 	}
@@ -187,7 +185,7 @@ func CreateUserRepo(c *context.APIContext, owner *db.User, opt api.CreateRepoOpt
 func Create(c *context.APIContext, opt api.CreateRepoOption) {
 	// Shouldn't reach this condition, but just in case.
 	if c.User.IsOrganization() {
-		c.Error(http.StatusUnprocessableEntity, "", "not allowed creating repository for organization")
+		c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Not allowed to create repository for organization."))
 		return
 	}
 	CreateUserRepo(c, c.User, opt)
@@ -196,12 +194,12 @@ func Create(c *context.APIContext, opt api.CreateRepoOption) {
 func CreateOrgRepo(c *context.APIContext, opt api.CreateRepoOption) {
 	org, err := db.GetOrgByName(c.Params(":org"))
 	if err != nil {
-		c.NotFoundOrServerError("GetOrgByName", errors.IsUserNotExist, err)
+		c.NotFoundOrError(err, "get organization by name")
 		return
 	}
 
 	if !org.IsOwnedBy(c.User.ID) {
-		c.Error(http.StatusForbidden, "", "given user is not owner of organization")
+		c.ErrorStatus(http.StatusForbidden, errors.New("Given user is not owner of organization."))
 		return
 	}
 	CreateUserRepo(c, org, opt)
@@ -214,28 +212,28 @@ func Migrate(c *context.APIContext, f form.MigrateRepo) {
 	if f.Uid != ctxUser.ID {
 		org, err := db.GetUserByID(f.Uid)
 		if err != nil {
-			if errors.IsUserNotExist(err) {
-				c.Error(http.StatusUnprocessableEntity, "", err)
+			if db.IsErrUserNotExist(err) {
+				c.ErrorStatus(http.StatusUnprocessableEntity, err)
 			} else {
-				c.Error(http.StatusInternalServerError, "GetUserByID", err)
+				c.Error(err, "get user by ID")
 			}
 			return
 		} else if !org.IsOrganization() && !c.User.IsAdmin {
-			c.Error(http.StatusForbidden, "", "given user is not an organization")
+			c.ErrorStatus(http.StatusForbidden, errors.New("Given user is not an organization."))
 			return
 		}
 		ctxUser = org
 	}
 
 	if c.HasError() {
-		c.Error(http.StatusUnprocessableEntity, "", c.GetErrMsg())
+		c.ErrorStatus(http.StatusUnprocessableEntity, errors.New(c.GetErrMsg()))
 		return
 	}
 
 	if ctxUser.IsOrganization() && !c.User.IsAdmin {
 		// Check ownership of organization.
 		if !ctxUser.IsOwnedBy(c.User.ID) {
-			c.Error(http.StatusForbidden, "", "Given user is not owner of organization")
+			c.ErrorStatus(http.StatusForbidden, errors.New("Given user is not owner of organization."))
 			return
 		}
 	}
@@ -246,16 +244,16 @@ func Migrate(c *context.APIContext, f form.MigrateRepo) {
 			addrErr := err.(db.ErrInvalidCloneAddr)
 			switch {
 			case addrErr.IsURLError:
-				c.Error(http.StatusUnprocessableEntity, "", err)
+				c.ErrorStatus(http.StatusUnprocessableEntity, err)
 			case addrErr.IsPermissionDenied:
-				c.Error(http.StatusUnprocessableEntity, "", "you are not allowed to import local repositories")
+				c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("You are not allowed to import local repositories."))
 			case addrErr.IsInvalidPath:
-				c.Error(http.StatusUnprocessableEntity, "", "invalid local path, it does not exist or not a directory")
+				c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Invalid local path, it does not exist or not a directory."))
 			default:
-				c.ServerError("ParseRemoteAddr", fmt.Errorf("unknown error type (ErrInvalidCloneAddr): %v", err))
+				c.Error(err, "unexpected error")
 			}
 		} else {
-			c.ServerError("ParseRemoteAddr", err)
+			c.Error(err, "parse remote address")
 		}
 		return
 	}
@@ -274,10 +272,10 @@ func Migrate(c *context.APIContext, f form.MigrateRepo) {
 			}
 		}
 
-		if errors.IsReachLimitOfRepo(err) {
-			c.Error(http.StatusUnprocessableEntity, "", err)
+		if db.IsErrReachLimitOfRepo(err) {
+			c.ErrorStatus(http.StatusUnprocessableEntity, err)
 		} else {
-			c.ServerError("MigrateRepository", errors.New(db.HandleMirrorCredentials(err.Error(), true)))
+			c.Error(errors.New(db.HandleMirrorCredentials(err.Error(), true)), "migrate repository")
 		}
 		return
 	}
@@ -290,17 +288,17 @@ func Migrate(c *context.APIContext, f form.MigrateRepo) {
 func parseOwnerAndRepo(c *context.APIContext) (*db.User, *db.Repository) {
 	owner, err := db.GetUserByName(c.Params(":username"))
 	if err != nil {
-		if errors.IsUserNotExist(err) {
-			c.Error(http.StatusUnprocessableEntity, "", err)
+		if db.IsErrUserNotExist(err) {
+			c.ErrorStatus(http.StatusUnprocessableEntity, err)
 		} else {
-			c.ServerError("GetUserByName", err)
+			c.Error(err, "get user by name")
 		}
 		return nil, nil
 	}
 
 	repo, err := db.GetRepositoryByName(owner.ID, c.Params(":reponame"))
 	if err != nil {
-		c.NotFoundOrServerError("GetRepositoryByName", errors.IsRepoNotExist, err)
+		c.NotFoundOrError(err, "get repository by name")
 		return nil, nil
 	}
 
@@ -327,12 +325,12 @@ func Delete(c *context.APIContext) {
 	}
 
 	if owner.IsOrganization() && !owner.IsOwnedBy(c.User.ID) {
-		c.Error(http.StatusForbidden, "", "given user is not owner of organization")
+		c.ErrorStatus(http.StatusForbidden, errors.New("Given user is not owner of organization."))
 		return
 	}
 
 	if err := db.DeleteRepository(owner.ID, repo.ID); err != nil {
-		c.ServerError("DeleteRepository", err)
+		c.Error(err, "delete repository")
 		return
 	}
 
@@ -343,14 +341,14 @@ func Delete(c *context.APIContext) {
 func ListForks(c *context.APIContext) {
 	forks, err := c.Repo.Repository.GetForks()
 	if err != nil {
-		c.ServerError("GetForks", err)
+		c.Error(err, "get forks")
 		return
 	}
 
 	apiForks := make([]*api.Repository, len(forks))
 	for i := range forks {
 		if err := forks[i].GetOwner(); err != nil {
-			c.ServerError("GetOwner", err)
+			c.Error(err, "get owner")
 			return
 		}
 		apiForks[i] = forks[i].APIFormat(&api.Permission{
@@ -386,7 +384,7 @@ func IssueTracker(c *context.APIContext, form api.EditIssueTrackerOption) {
 	}
 
 	if err := db.UpdateRepository(repo, false); err != nil {
-		c.ServerError("UpdateRepository", err)
+		c.Error(err, "update repository")
 		return
 	}
 

+ 3 - 3
internal/route/api/v1/repo/tree.go

@@ -16,20 +16,20 @@ import (
 func GetRepoGitTree(c *context.APIContext) {
 	gitRepo, err := git.Open(c.Repo.Repository.RepoPath())
 	if err != nil {
-		c.ServerError("open repository", err)
+		c.Error(err, "open repository")
 		return
 	}
 
 	sha := c.Params(":sha")
 	tree, err := gitRepo.LsTree(sha)
 	if err != nil {
-		c.NotFoundOrServerError("get tree", gitutil.IsErrRevisionNotExist, err)
+		c.NotFoundOrError(gitutil.NewError(err), "get tree")
 		return
 	}
 
 	entries, err := tree.Entries()
 	if err != nil {
-		c.ServerError("list entries", err)
+		c.Error(err, "list entries")
 		return
 	}
 

+ 3 - 3
internal/route/api/v1/user/app.go

@@ -17,7 +17,7 @@ import (
 func ListAccessTokens(c *context.APIContext) {
 	tokens, err := db.ListAccessTokens(c.User.ID)
 	if err != nil {
-		c.ServerError("ListAccessTokens", err)
+		c.Error(err, "list access tokens")
 		return
 	}
 
@@ -35,9 +35,9 @@ func CreateAccessToken(c *context.APIContext, form api.CreateAccessTokenOption)
 	}
 	if err := db.NewAccessToken(t); err != nil {
 		if errors.IsAccessTokenNameAlreadyExist(err) {
-			c.Error(http.StatusUnprocessableEntity, "", err)
+			c.ErrorStatus(http.StatusUnprocessableEntity, err)
 		} else {
-			c.ServerError("NewAccessToken", err)
+			c.Error(err, "new access token")
 		}
 		return
 	}

+ 8 - 7
internal/route/api/v1/user/email.go

@@ -5,25 +5,26 @@
 package user
 
 import (
-	convert2 "gogs.io/gogs/internal/route/api/v1/convert"
 	"net/http"
 
 	api "github.com/gogs/go-gogs-client"
+	"github.com/pkg/errors"
 
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
+	"gogs.io/gogs/internal/route/api/v1/convert"
 )
 
 func ListEmails(c *context.APIContext) {
 	emails, err := db.GetEmailAddresses(c.User.ID)
 	if err != nil {
-		c.ServerError("GetEmailAddresses", err)
+		c.Error(err, "get email addresses")
 		return
 	}
 	apiEmails := make([]*api.Email, len(emails))
 	for i := range emails {
-		apiEmails[i] = convert2.ToEmail(emails[i])
+		apiEmails[i] = convert.ToEmail(emails[i])
 	}
 	c.JSONSuccess(&apiEmails)
 }
@@ -45,16 +46,16 @@ func AddEmail(c *context.APIContext, form api.CreateEmailOption) {
 
 	if err := db.AddEmailAddresses(emails); err != nil {
 		if db.IsErrEmailAlreadyUsed(err) {
-			c.Error(http.StatusUnprocessableEntity, "", "email address has been used: "+err.(db.ErrEmailAlreadyUsed).Email)
+			c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("email address has been used: "+err.(db.ErrEmailAlreadyUsed).Email))
 		} else {
-			c.Error(http.StatusInternalServerError, "AddEmailAddresses", err)
+			c.Error(err, "add email addresses")
 		}
 		return
 	}
 
 	apiEmails := make([]*api.Email, len(emails))
 	for i := range emails {
-		apiEmails[i] = convert2.ToEmail(emails[i])
+		apiEmails[i] = convert.ToEmail(emails[i])
 	}
 	c.JSON(http.StatusCreated, &apiEmails)
 }
@@ -74,7 +75,7 @@ func DeleteEmail(c *context.APIContext, form api.CreateEmailOption) {
 	}
 
 	if err := db.DeleteEmailAddresses(emails); err != nil {
-		c.Error(http.StatusInternalServerError, "DeleteEmailAddresses", err)
+		c.Error(err, "delete email addresses")
 		return
 	}
 	c.NoContent()

+ 4 - 4
internal/route/api/v1/user/follower.go

@@ -22,7 +22,7 @@ func responseApiUsers(c *context.APIContext, users []*db.User) {
 func listUserFollowers(c *context.APIContext, u *db.User) {
 	users, err := u.GetFollowers(c.QueryInt("page"))
 	if err != nil {
-		c.ServerError("GetUserFollowers", err)
+		c.Error(err, "get followers")
 		return
 	}
 	responseApiUsers(c, users)
@@ -43,7 +43,7 @@ func ListFollowers(c *context.APIContext) {
 func listUserFollowing(c *context.APIContext, u *db.User) {
 	users, err := u.GetFollowing(c.QueryInt("page"))
 	if err != nil {
-		c.ServerError("GetFollowing", err)
+		c.Error(err, "get following")
 		return
 	}
 	responseApiUsers(c, users)
@@ -95,7 +95,7 @@ func Follow(c *context.APIContext) {
 		return
 	}
 	if err := db.FollowUser(c.User.ID, target.ID); err != nil {
-		c.ServerError("FollowUser", err)
+		c.Error(err, "follow user")
 		return
 	}
 	c.NoContent()
@@ -107,7 +107,7 @@ func Unfollow(c *context.APIContext) {
 		return
 	}
 	if err := db.UnfollowUser(c.User.ID, target.ID); err != nil {
-		c.ServerError("UnfollowUser", err)
+		c.Error(err, "unfollow user")
 		return
 	}
 	c.NoContent()

+ 15 - 14
internal/route/api/v1/user/key.go

@@ -5,21 +5,22 @@
 package user
 
 import (
-	api "github.com/gogs/go-gogs-client"
-	convert2 "gogs.io/gogs/internal/route/api/v1/convert"
-	repo2 "gogs.io/gogs/internal/route/api/v1/repo"
 	"net/http"
 
+	api "github.com/gogs/go-gogs-client"
+	"github.com/pkg/errors"
+
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
+	"gogs.io/gogs/internal/route/api/v1/convert"
+	"gogs.io/gogs/internal/route/api/v1/repo"
 )
 
 func GetUserByParamsName(c *context.APIContext, name string) *db.User {
 	user, err := db.GetUserByName(c.Params(name))
 	if err != nil {
-		c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
+		c.NotFoundOrError(err, "get user by name")
 		return nil
 	}
 	return user
@@ -37,14 +38,14 @@ func composePublicKeysAPILink() string {
 func listPublicKeys(c *context.APIContext, uid int64) {
 	keys, err := db.ListPublicKeys(uid)
 	if err != nil {
-		c.ServerError("ListPublicKeys", err)
+		c.Error(err, "list public keys")
 		return
 	}
 
 	apiLink := composePublicKeysAPILink()
 	apiKeys := make([]*api.PublicKey, len(keys))
 	for i := range keys {
-		apiKeys[i] = convert2.ToPublicKey(apiLink, keys[i])
+		apiKeys[i] = convert.ToPublicKey(apiLink, keys[i])
 	}
 
 	c.JSONSuccess(&apiKeys)
@@ -65,29 +66,29 @@ func ListPublicKeys(c *context.APIContext) {
 func GetPublicKey(c *context.APIContext) {
 	key, err := db.GetPublicKeyByID(c.ParamsInt64(":id"))
 	if err != nil {
-		c.NotFoundOrServerError("GetPublicKeyByID", db.IsErrKeyNotExist, err)
+		c.NotFoundOrError(err, "get public key by ID")
 		return
 	}
 
 	apiLink := composePublicKeysAPILink()
-	c.JSONSuccess(convert2.ToPublicKey(apiLink, key))
+	c.JSONSuccess(convert.ToPublicKey(apiLink, key))
 }
 
 // CreateUserPublicKey creates new public key to given user by ID.
 func CreateUserPublicKey(c *context.APIContext, form api.CreateKeyOption, uid int64) {
 	content, err := db.CheckPublicKeyString(form.Key)
 	if err != nil {
-		repo2.HandleCheckKeyStringError(c, err)
+		repo.HandleCheckKeyStringError(c, err)
 		return
 	}
 
 	key, err := db.AddPublicKey(uid, form.Title, content)
 	if err != nil {
-		repo2.HandleAddKeyError(c, err)
+		repo.HandleAddKeyError(c, err)
 		return
 	}
 	apiLink := composePublicKeysAPILink()
-	c.JSON(http.StatusCreated, convert2.ToPublicKey(apiLink, key))
+	c.JSON(http.StatusCreated, convert.ToPublicKey(apiLink, key))
 }
 
 func CreatePublicKey(c *context.APIContext, form api.CreateKeyOption) {
@@ -97,9 +98,9 @@ func CreatePublicKey(c *context.APIContext, form api.CreateKeyOption) {
 func DeletePublicKey(c *context.APIContext) {
 	if err := db.DeletePublicKey(c.User, c.ParamsInt64(":id")); err != nil {
 		if db.IsErrKeyAccessDenied(err) {
-			c.Error(http.StatusForbidden, "", "you do not have access to this key")
+			c.ErrorStatus(http.StatusForbidden, errors.New("You do not have access to this key."))
 		} else {
-			c.Error(http.StatusInternalServerError, "DeletePublicKey", err)
+			c.Error(err, "delete public key")
 		}
 		return
 	}

+ 1 - 2
internal/route/api/v1/user/user.go

@@ -13,7 +13,6 @@ import (
 
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
 	"gogs.io/gogs/internal/markup"
 )
 
@@ -58,7 +57,7 @@ func Search(c *context.APIContext) {
 func GetInfo(c *context.APIContext) {
 	u, err := db.GetUserByName(c.Params(":username"))
 	if err != nil {
-		c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
+		c.NotFoundOrError(err, "get user by name")
 		return
 	}
 

+ 1 - 1
internal/route/dev/template.go

@@ -20,5 +20,5 @@ func TemplatePreview(c *context.Context) {
 	c.Data["ResetPwdCodeLives"] = conf.Auth.ResetPasswordCodeLives / 60
 	c.Data["CurDbValue"] = ""
 
-	c.HTML(200, (c.Params("*")))
+	c.Success( (c.Params("*")))
 }

+ 7 - 7
internal/route/home.go

@@ -6,11 +6,11 @@ package route
 
 import (
 	"github.com/unknwon/paginater"
-	user2 "gogs.io/gogs/internal/route/user"
 
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
+	"gogs.io/gogs/internal/route/user"
 )
 
 const (
@@ -24,9 +24,9 @@ func Home(c *context.Context) {
 	if c.IsLogged {
 		if !c.User.IsActive && conf.Auth.RequireEmailConfirmation {
 			c.Data["Title"] = c.Tr("auth.active_your_account")
-			c.Success(user2.ACTIVATE)
+			c.Success(user.ACTIVATE)
 		} else {
-			user2.Dashboard(c)
+			user.Dashboard(c)
 		}
 		return
 	}
@@ -61,7 +61,7 @@ func ExploreRepos(c *context.Context) {
 		PageSize: conf.UI.ExplorePagingNum,
 	})
 	if err != nil {
-		c.ServerError("SearchRepositoryByName", err)
+		c.Error(err, "search repository by name")
 		return
 	}
 	c.Data["Keyword"] = keyword
@@ -69,7 +69,7 @@ func ExploreRepos(c *context.Context) {
 	c.Data["Page"] = paginater.New(int(count), conf.UI.ExplorePagingNum, page, 5)
 
 	if err = db.RepositoryList(repos).LoadAttributes(); err != nil {
-		c.ServerError("RepositoryList.LoadAttributes", err)
+		c.Error(err, "load attributes")
 		return
 	}
 	c.Data["Repos"] = repos
@@ -102,7 +102,7 @@ func RenderUserSearch(c *context.Context, opts *UserSearchOptions) {
 	if len(keyword) == 0 {
 		users, err = opts.Ranger(page, opts.PageSize)
 		if err != nil {
-			c.ServerError("Ranger", err)
+			c.Error(err, "ranger")
 			return
 		}
 		count = opts.Counter()
@@ -115,7 +115,7 @@ func RenderUserSearch(c *context.Context, opts *UserSearchOptions) {
 			PageSize: opts.PageSize,
 		})
 		if err != nil {
-			c.ServerError("SearchUserByName", err)
+			c.Error(err, "search user by name")
 			return
 		}
 	}

+ 10 - 11
internal/route/org/members.go

@@ -11,7 +11,6 @@ import (
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
 )
 
 const (
@@ -25,12 +24,12 @@ func Members(c *context.Context) {
 	c.Data["PageIsOrgMembers"] = true
 
 	if err := org.GetMembers(); err != nil {
-		c.Handle(500, "GetMembers", err)
+		c.Error(err, "get members")
 		return
 	}
 	c.Data["Members"] = org.Members
 
-	c.HTML(200, MEMBERS)
+	c.Success(MEMBERS)
 }
 
 func MembersAction(c *context.Context) {
@@ -45,19 +44,19 @@ func MembersAction(c *context.Context) {
 	switch c.Params(":action") {
 	case "private":
 		if c.User.ID != uid && !c.Org.IsOwner {
-			c.Error(404)
+			c.NotFound()
 			return
 		}
 		err = db.ChangeOrgUserStatus(org.ID, uid, false)
 	case "public":
 		if c.User.ID != uid && !c.Org.IsOwner {
-			c.Error(404)
+			c.NotFound()
 			return
 		}
 		err = db.ChangeOrgUserStatus(org.ID, uid, true)
 	case "remove":
 		if !c.Org.IsOwner {
-			c.Error(404)
+			c.NotFound()
 			return
 		}
 		err = org.RemoveMember(uid)
@@ -77,7 +76,7 @@ func MembersAction(c *context.Context) {
 
 	if err != nil {
 		log.Error("Action(%s): %v", c.Params(":action"), err)
-		c.JSON(200, map[string]interface{}{
+		c.JSONSuccess( map[string]interface{}{
 			"ok":  false,
 			"err": err.Error(),
 		})
@@ -100,17 +99,17 @@ func Invitation(c *context.Context) {
 		uname := c.Query("uname")
 		u, err := db.GetUserByName(uname)
 		if err != nil {
-			if errors.IsUserNotExist(err) {
+			if db.IsErrUserNotExist(err) {
 				c.Flash.Error(c.Tr("form.user_not_exist"))
 				c.Redirect(c.Org.OrgLink + "/invitations/new")
 			} else {
-				c.Handle(500, " GetUserByName", err)
+				c.Error(err, "get user by name")
 			}
 			return
 		}
 
 		if err = org.AddMember(u.ID); err != nil {
-			c.Handle(500, " AddMember", err)
+			c.Error(err, "add member")
 			return
 		}
 
@@ -119,5 +118,5 @@ func Invitation(c *context.Context) {
 		return
 	}
 
-	c.HTML(200, MEMBER_INVITE)
+	c.Success(MEMBER_INVITE)
 }

+ 6 - 7
internal/route/org/org.go

@@ -7,7 +7,6 @@ package org
 import (
 	log "unknwon.dev/clog/v2"
 
-	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
 	"gogs.io/gogs/internal/form"
@@ -18,15 +17,15 @@ const (
 )
 
 func Create(c *context.Context) {
-	c.Data["Title"] = c.Tr("new_org")
-	c.HTML(200, CREATE)
+	c.Title("new_org")
+	c.Success(CREATE)
 }
 
 func CreatePost(c *context.Context, f form.CreateOrg) {
-	c.Data["Title"] = c.Tr("new_org")
+	c.Title("new_org")
 
 	if c.HasError() {
-		c.HTML(200, CREATE)
+		c.Success(CREATE)
 		return
 	}
 
@@ -46,11 +45,11 @@ func CreatePost(c *context.Context, f form.CreateOrg) {
 		case db.IsErrNamePatternNotAllowed(err):
 			c.RenderWithErr(c.Tr("org.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), CREATE, &f)
 		default:
-			c.Handle(500, "CreateOrganization", err)
+			c.Error(err, "create organization")
 		}
 		return
 	}
 	log.Trace("Organization created: %s", org.Name)
 
-	c.Redirect(conf.Server.Subpath + "/org/" + f.OrgName + "/dashboard")
+	c.RedirectSubpath("/org/" + f.OrgName + "/dashboard")
 }

+ 14 - 15
internal/route/org/setting.go

@@ -12,7 +12,6 @@ import (
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
 	"gogs.io/gogs/internal/form"
 	"gogs.io/gogs/internal/route/user"
 )
@@ -24,17 +23,17 @@ const (
 )
 
 func Settings(c *context.Context) {
-	c.Data["Title"] = c.Tr("org.settings")
+	c.Title("org.settings")
 	c.Data["PageIsSettingsOptions"] = true
-	c.HTML(200, SETTINGS_OPTIONS)
+	c.Success(SETTINGS_OPTIONS)
 }
 
 func SettingsPost(c *context.Context, f form.UpdateOrgSetting) {
-	c.Data["Title"] = c.Tr("org.settings")
+	c.Title("org.settings")
 	c.Data["PageIsSettingsOptions"] = true
 
 	if c.HasError() {
-		c.HTML(200, SETTINGS_OPTIONS)
+		c.Success(SETTINGS_OPTIONS)
 		return
 	}
 
@@ -44,7 +43,7 @@ func SettingsPost(c *context.Context, f form.UpdateOrgSetting) {
 	if org.LowerName != strings.ToLower(f.Name) {
 		isExist, err := db.IsUserExist(org.ID, f.Name)
 		if err != nil {
-			c.Handle(500, "IsUserExist", err)
+			c.Error(err, "check if user exists")
 			return
 		} else if isExist {
 			c.Data["OrgName"] = true
@@ -58,7 +57,7 @@ func SettingsPost(c *context.Context, f form.UpdateOrgSetting) {
 			case db.IsErrNamePatternNotAllowed(err):
 				c.RenderWithErr(c.Tr("user.form.name_pattern_not_allowed"), SETTINGS_OPTIONS, &f)
 			default:
-				c.Handle(500, "ChangeUserName", err)
+				c.Error(err, "change user name")
 			}
 			return
 		}
@@ -79,7 +78,7 @@ func SettingsPost(c *context.Context, f form.UpdateOrgSetting) {
 	org.Website = f.Website
 	org.Location = f.Location
 	if err := db.UpdateUser(org); err != nil {
-		c.Handle(500, "UpdateUser", err)
+		c.Error(err, "update user")
 		return
 	}
 	log.Trace("Organization setting updated: %s", org.Name)
@@ -113,10 +112,10 @@ func SettingsDelete(c *context.Context) {
 	org := c.Org.Organization
 	if c.Req.Method == "POST" {
 		if _, err := db.UserLogin(c.User.Name, c.Query("password"), c.User.LoginSource); err != nil {
-			if errors.IsUserNotExist(err) {
+			if db.IsErrUserNotExist(err) {
 				c.RenderWithErr(c.Tr("form.enterred_invalid_password"), SETTINGS_DELETE, nil)
 			} else {
-				c.ServerError("UserLogin", err)
+				c.Error(err, "authenticate user")
 			}
 			return
 		}
@@ -126,7 +125,7 @@ func SettingsDelete(c *context.Context) {
 				c.Flash.Error(c.Tr("form.org_still_own_repo"))
 				c.Redirect(c.Org.OrgLink + "/settings/delete")
 			} else {
-				c.ServerError("DeleteOrganization", err)
+				c.Error(err, "delete organization")
 			}
 		} else {
 			log.Trace("Organization deleted: %s", org.Name)
@@ -139,7 +138,7 @@ func SettingsDelete(c *context.Context) {
 }
 
 func Webhooks(c *context.Context) {
-	c.Data["Title"] = c.Tr("org.settings")
+	c.Title("org.settings")
 	c.Data["PageIsSettingsHooks"] = true
 	c.Data["BaseLink"] = c.Org.OrgLink
 	c.Data["Description"] = c.Tr("org.settings.hooks_desc")
@@ -147,12 +146,12 @@ func Webhooks(c *context.Context) {
 
 	ws, err := db.GetWebhooksByOrgID(c.Org.Organization.ID)
 	if err != nil {
-		c.Handle(500, "GetWebhooksByOrgId", err)
+		c.Error(err, "get webhooks by organization ID")
 		return
 	}
 
 	c.Data["Webhooks"] = ws
-	c.HTML(200, SETTINGS_WEBHOOKS)
+	c.Success(SETTINGS_WEBHOOKS)
 }
 
 func DeleteWebhook(c *context.Context) {
@@ -162,7 +161,7 @@ func DeleteWebhook(c *context.Context) {
 		c.Flash.Success(c.Tr("repo.settings.webhook_deletion_success"))
 	}
 
-	c.JSON(200, map[string]interface{}{
+	c.JSONSuccess( map[string]interface{}{
 		"redirect": c.Org.OrgLink + "/settings/hooks",
 	})
 }

+ 26 - 26
internal/route/org/teams.go

@@ -5,6 +5,7 @@
 package org
 
 import (
+	"net/http"
 	"path"
 
 	"github.com/unknwon/com"
@@ -12,7 +13,6 @@ import (
 
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
 	"gogs.io/gogs/internal/form"
 )
 
@@ -30,13 +30,13 @@ func Teams(c *context.Context) {
 
 	for _, t := range org.Teams {
 		if err := t.GetMembers(); err != nil {
-			c.Handle(500, "GetMembers", err)
+			c.Error(err, "get members")
 			return
 		}
 	}
 	c.Data["Teams"] = org.Teams
 
-	c.HTML(200, TEAMS)
+	c.Success(TEAMS)
 }
 
 func TeamsAction(c *context.Context) {
@@ -51,7 +51,7 @@ func TeamsAction(c *context.Context) {
 	switch c.Params(":action") {
 	case "join":
 		if !c.Org.IsOwner {
-			c.Error(404)
+			c.NotFound()
 			return
 		}
 		err = c.Org.Team.AddMember(c.User.ID)
@@ -59,25 +59,25 @@ func TeamsAction(c *context.Context) {
 		err = c.Org.Team.RemoveMember(c.User.ID)
 	case "remove":
 		if !c.Org.IsOwner {
-			c.Error(404)
+			c.NotFound()
 			return
 		}
 		err = c.Org.Team.RemoveMember(uid)
 		page = "team"
 	case "add":
 		if !c.Org.IsOwner {
-			c.Error(404)
+			c.NotFound()
 			return
 		}
 		uname := c.Query("uname")
 		var u *db.User
 		u, err = db.GetUserByName(uname)
 		if err != nil {
-			if errors.IsUserNotExist(err) {
+			if db.IsErrUserNotExist(err) {
 				c.Flash.Error(c.Tr("form.user_not_exist"))
 				c.Redirect(c.Org.OrgLink + "/teams/" + c.Org.Team.LowerName)
 			} else {
-				c.Handle(500, " GetUserByName", err)
+				c.Error(err, "get user by name")
 			}
 			return
 		}
@@ -91,7 +91,7 @@ func TeamsAction(c *context.Context) {
 			c.Flash.Error(c.Tr("form.last_org_owner"))
 		} else {
 			log.Error("Action(%s): %v", c.Params(":action"), err)
-			c.JSON(200, map[string]interface{}{
+			c.JSONSuccess(map[string]interface{}{
 				"ok":  false,
 				"err": err.Error(),
 			})
@@ -109,7 +109,7 @@ func TeamsAction(c *context.Context) {
 
 func TeamsRepoAction(c *context.Context) {
 	if !c.Org.IsOwner {
-		c.Error(404)
+		c.NotFound()
 		return
 	}
 
@@ -120,12 +120,13 @@ func TeamsRepoAction(c *context.Context) {
 		var repo *db.Repository
 		repo, err = db.GetRepositoryByName(c.Org.Organization.ID, repoName)
 		if err != nil {
-			if errors.IsRepoNotExist(err) {
+			if db.IsErrRepoNotExist(err) {
 				c.Flash.Error(c.Tr("org.teams.add_nonexistent_repo"))
 				c.Redirect(c.Org.OrgLink + "/teams/" + c.Org.Team.LowerName + "/repositories")
 				return
 			}
-			c.Handle(500, "GetRepositoryByName", err)
+
+			c.Error(err, "get repository by name")
 			return
 		}
 		err = c.Org.Team.AddRepository(repo)
@@ -134,8 +135,7 @@ func TeamsRepoAction(c *context.Context) {
 	}
 
 	if err != nil {
-		log.Error("Action(%s): '%s' %v", c.Params(":action"), c.Org.Team.Name, err)
-		c.Handle(500, "TeamsRepoAction", err)
+		c.Errorf(err, "action %q", c.Params(":action"))
 		return
 	}
 	c.Redirect(c.Org.OrgLink + "/teams/" + c.Org.Team.LowerName + "/repositories")
@@ -146,7 +146,7 @@ func NewTeam(c *context.Context) {
 	c.Data["PageIsOrgTeams"] = true
 	c.Data["PageIsOrgTeamsNew"] = true
 	c.Data["Team"] = &db.Team{}
-	c.HTML(200, TEAM_NEW)
+	c.Success(TEAM_NEW)
 }
 
 func NewTeamPost(c *context.Context, f form.CreateTeam) {
@@ -163,7 +163,7 @@ func NewTeamPost(c *context.Context, f form.CreateTeam) {
 	c.Data["Team"] = t
 
 	if c.HasError() {
-		c.HTML(200, TEAM_NEW)
+		c.Success(TEAM_NEW)
 		return
 	}
 
@@ -175,7 +175,7 @@ func NewTeamPost(c *context.Context, f form.CreateTeam) {
 		case db.IsErrNameReserved(err):
 			c.RenderWithErr(c.Tr("org.form.team_name_reserved", err.(db.ErrNameReserved).Name), TEAM_NEW, &f)
 		default:
-			c.Handle(500, "NewTeam", err)
+			c.Error(err, "new team")
 		}
 		return
 	}
@@ -187,20 +187,20 @@ func TeamMembers(c *context.Context) {
 	c.Data["Title"] = c.Org.Team.Name
 	c.Data["PageIsOrgTeams"] = true
 	if err := c.Org.Team.GetMembers(); err != nil {
-		c.Handle(500, "GetMembers", err)
+		c.Error(err, "get members")
 		return
 	}
-	c.HTML(200, TEAM_MEMBERS)
+	c.Success(TEAM_MEMBERS)
 }
 
 func TeamRepositories(c *context.Context) {
 	c.Data["Title"] = c.Org.Team.Name
 	c.Data["PageIsOrgTeams"] = true
 	if err := c.Org.Team.GetRepositories(); err != nil {
-		c.Handle(500, "GetRepositories", err)
+		c.Error(err, "get repositories")
 		return
 	}
-	c.HTML(200, TEAM_REPOSITORIES)
+	c.Success(TEAM_REPOSITORIES)
 }
 
 func EditTeam(c *context.Context) {
@@ -208,7 +208,7 @@ func EditTeam(c *context.Context) {
 	c.Data["PageIsOrgTeams"] = true
 	c.Data["team_name"] = c.Org.Team.Name
 	c.Data["desc"] = c.Org.Team.Description
-	c.HTML(200, TEAM_NEW)
+	c.Success(TEAM_NEW)
 }
 
 func EditTeamPost(c *context.Context, f form.CreateTeam) {
@@ -218,7 +218,7 @@ func EditTeamPost(c *context.Context, f form.CreateTeam) {
 	c.Data["Team"] = t
 
 	if c.HasError() {
-		c.HTML(200, TEAM_NEW)
+		c.Success(TEAM_NEW)
 		return
 	}
 
@@ -234,7 +234,7 @@ func EditTeamPost(c *context.Context, f form.CreateTeam) {
 		case "admin":
 			auth = db.ACCESS_MODE_ADMIN
 		default:
-			c.Error(401)
+			c.Status(http.StatusUnauthorized)
 			return
 		}
 
@@ -251,7 +251,7 @@ func EditTeamPost(c *context.Context, f form.CreateTeam) {
 		case db.IsErrTeamAlreadyExist(err):
 			c.RenderWithErr(c.Tr("form.team_name_been_taken"), TEAM_NEW, &f)
 		default:
-			c.Handle(500, "UpdateTeam", err)
+			c.Error(err, "update team")
 		}
 		return
 	}
@@ -265,7 +265,7 @@ func DeleteTeam(c *context.Context) {
 		c.Flash.Success(c.Tr("org.teams.delete_team_success"))
 	}
 
-	c.JSON(200, map[string]interface{}{
+	c.JSONSuccess(map[string]interface{}{
 		"redirect": c.Org.OrgLink + "/teams",
 	})
 }

+ 5 - 5
internal/route/repo/branch.go

@@ -31,13 +31,13 @@ type Branch struct {
 func loadBranches(c *context.Context) []*Branch {
 	rawBranches, err := c.Repo.Repository.GetBranches()
 	if err != nil {
-		c.Handle(500, "GetBranches", err)
+		c.Error(err, "get branches")
 		return nil
 	}
 
 	protectBranches, err := db.GetProtectBranchesByRepoID(c.Repo.Repository.ID)
 	if err != nil {
-		c.Handle(500, "GetProtectBranchesByRepoID", err)
+		c.Error(err, "get protect branches by repository ID")
 		return nil
 	}
 
@@ -45,7 +45,7 @@ func loadBranches(c *context.Context) []*Branch {
 	for i := range rawBranches {
 		commit, err := rawBranches[i].GetCommit()
 		if err != nil {
-			c.Handle(500, "GetCommit", err)
+			c.Error(err, "get commit")
 			return nil
 		}
 
@@ -91,7 +91,7 @@ func Branches(c *context.Context) {
 
 	c.Data["ActiveBranches"] = activeBranches
 	c.Data["StaleBranches"] = staleBranches
-	c.HTML(200, BRANCHES_OVERVIEW)
+	c.Success( BRANCHES_OVERVIEW)
 }
 
 func AllBranches(c *context.Context) {
@@ -104,7 +104,7 @@ func AllBranches(c *context.Context) {
 	}
 	c.Data["Branches"] = branches
 
-	c.HTML(200, BRANCHES_ALL)
+	c.Success( BRANCHES_ALL)
 }
 
 func DeleteBranchPost(c *context.Context) {

+ 11 - 11
internal/route/repo/commit.go

@@ -54,7 +54,7 @@ func renderCommits(c *context.Context, filename string) {
 
 	commits, err := c.Repo.Commit.CommitsByPage(page, pageSize, git.CommitsByPageOptions{Path: filename})
 	if err != nil {
-		c.ServerError("paging commits", err)
+		c.Error(err, "paging commits")
 		return
 	}
 
@@ -73,7 +73,7 @@ func renderCommits(c *context.Context, filename string) {
 
 	c.Data["Username"] = c.Repo.Owner.Name
 	c.Data["Reponame"] = c.Repo.Repository.Name
-	c.HTML(200, COMMITS)
+	c.Success(COMMITS)
 }
 
 func Commits(c *context.Context) {
@@ -91,7 +91,7 @@ func SearchCommits(c *context.Context) {
 
 	commits, err := c.Repo.Commit.SearchCommits(keyword)
 	if err != nil {
-		c.ServerError("SearchCommits", err)
+		c.Error(err, "search commits")
 		return
 	}
 
@@ -102,7 +102,7 @@ func SearchCommits(c *context.Context) {
 	c.Data["Username"] = c.Repo.Owner.Name
 	c.Data["Reponame"] = c.Repo.Repository.Name
 	c.Data["Branch"] = c.Repo.BranchName
-	c.HTML(200, COMMITS)
+	c.Success(COMMITS)
 }
 
 func FileHistory(c *context.Context) {
@@ -119,7 +119,7 @@ func Diff(c *context.Context) {
 
 	commit, err := c.Repo.GitRepo.CatFileCommit(commitID)
 	if err != nil {
-		c.NotFoundOrServerError("get commit by ID", gitutil.IsErrRevisionNotExist, err)
+		c.NotFoundOrError(gitutil.NewError(err), "get commit by ID")
 		return
 	}
 
@@ -127,7 +127,7 @@ func Diff(c *context.Context) {
 		commitID, conf.Git.MaxDiffFiles, conf.Git.MaxDiffLines, conf.Git.MaxDiffLineChars,
 	)
 	if err != nil {
-		c.NotFoundOrServerError("get diff", gitutil.IsErrRevisionNotExist, err)
+		c.NotFoundOrError(gitutil.NewError(err), "get diff")
 		return
 	}
 
@@ -171,7 +171,7 @@ func RawDiff(c *context.Context) {
 		git.RawDiffFormat(c.Params(":ext")),
 		c.Resp,
 	); err != nil {
-		c.NotFoundOrServerError("get raw diff", gitutil.IsErrRevisionNotExist, err)
+		c.NotFoundOrError(gitutil.NewError(err), "get raw diff")
 		return
 	}
 }
@@ -185,7 +185,7 @@ func CompareDiff(c *context.Context) {
 
 	commit, err := c.Repo.GitRepo.CatFileCommit(afterCommitID)
 	if err != nil {
-		c.Handle(404, "GetCommit", err)
+		c.NotFoundOrError(gitutil.NewError(err), "get head commit")
 		return
 	}
 
@@ -194,13 +194,13 @@ func CompareDiff(c *context.Context) {
 		git.DiffOptions{Base: beforeCommitID},
 	)
 	if err != nil {
-		c.ServerError("get diff", err)
+		c.NotFoundOrError(gitutil.NewError(err), "get diff")
 		return
 	}
 
 	commits, err := commit.CommitsAfter(beforeCommitID)
 	if err != nil {
-		c.ServerError("get commits after", err)
+		c.NotFoundOrError(gitutil.NewError(err), "get commits after")
 		return
 	}
 
@@ -220,5 +220,5 @@ func CompareDiff(c *context.Context) {
 	c.Data["SourcePath"] = conf.Server.Subpath + "/" + path.Join(userName, repoName, "src", afterCommitID)
 	c.Data["BeforeSourcePath"] = conf.Server.Subpath + "/" + path.Join(userName, repoName, "src", beforeCommitID)
 	c.Data["RawPath"] = conf.Server.Subpath + "/" + path.Join(userName, repoName, "raw", afterCommitID)
-	c.HTML(200, DIFF)
+	c.Success(DIFF)
 }

+ 2 - 2
internal/route/repo/download.go

@@ -51,12 +51,12 @@ func ServeBlob(c *context.Context, blob *git.Blob) error {
 func SingleDownload(c *context.Context) {
 	blob, err := c.Repo.Commit.Blob(c.Repo.TreePath)
 	if err != nil {
-		c.NotFoundOrServerError("get blob", gitutil.IsErrRevisionNotExist, err)
+		c.NotFoundOrError(gitutil.NewError(err), "get blob")
 		return
 	}
 
 	if err = ServeBlob(c, blob); err != nil {
-		c.ServerError("serve blob", err)
+		c.Error(err, "serve blob")
 		return
 	}
 }

+ 18 - 18
internal/route/repo/editor.go

@@ -56,7 +56,7 @@ func editFile(c *context.Context, isNewFile bool) {
 	if !isNewFile {
 		entry, err := c.Repo.Commit.TreeEntry(c.Repo.TreePath)
 		if err != nil {
-			c.NotFoundOrServerError("get tree entry", gitutil.IsErrRevisionNotExist, err)
+			c.NotFoundOrError(gitutil.NewError(err), "get tree entry")
 			return
 		}
 
@@ -69,7 +69,7 @@ func editFile(c *context.Context, isNewFile bool) {
 		blob := entry.Blob()
 		p, err := blob.Bytes()
 		if err != nil {
-			c.ServerError("blob.Data", err)
+			c.Error(err, "get blob data")
 			return
 		}
 
@@ -182,7 +182,7 @@ func editFilePost(c *context.Context, f form.EditRepoFile, isNewFile bool) {
 				break
 			}
 
-			c.ServerError("Repo.Commit.GetTreeEntryByPath", err)
+			c.Error(err, "get tree entry")
 			return
 		}
 		if index != len(treeNames)-1 {
@@ -211,14 +211,14 @@ func editFilePost(c *context.Context, f form.EditRepoFile, isNewFile bool) {
 				c.FormErr("TreePath")
 				c.RenderWithErr(c.Tr("repo.editor.file_editing_no_longer_exists", oldTreePath), EDIT_FILE, &f)
 			} else {
-				c.ServerError("GetTreeEntryByPath", err)
+				c.Error(err, "get tree entry")
 			}
 			return
 		}
 		if lastCommit != c.Repo.CommitID {
 			files, err := c.Repo.Commit.FilesChangedAfter(lastCommit)
 			if err != nil {
-				c.ServerError("GetFilesChangedSinceCommit", err)
+				c.Error(err, "get changed files")
 				return
 			}
 
@@ -236,7 +236,7 @@ func editFilePost(c *context.Context, f form.EditRepoFile, isNewFile bool) {
 		entry, err := c.Repo.Commit.TreeEntry(f.TreePath)
 		if err != nil {
 			if !gitutil.IsErrRevisionNotExist(err) {
-				c.ServerError("GetTreeEntryByPath", err)
+				c.Error(err, "get tree entry")
 				return
 			}
 		}
@@ -297,26 +297,26 @@ func DiffPreviewPost(c *context.Context, f form.EditPreviewDiff) {
 
 	entry, err := c.Repo.Commit.TreeEntry(treePath)
 	if err != nil {
-		c.Error(500, "GetTreeEntryByPath: "+err.Error())
+		c.Error(err, "get tree entry")
 		return
 	} else if entry.IsTree() {
-		c.Error(422)
+		c.Status(http.StatusUnprocessableEntity)
 		return
 	}
 
 	diff, err := c.Repo.Repository.GetDiffPreview(c.Repo.BranchName, treePath, f.Content)
 	if err != nil {
-		c.Error(500, "GetDiffPreview: "+err.Error())
+		c.Error(err, "get diff preview")
 		return
 	}
 
 	if diff.NumFiles() == 0 {
-		c.PlainText(200, []byte(c.Tr("repo.editor.no_changes_to_show")))
+		c.PlainText(http.StatusOK, c.Tr("repo.editor.no_changes_to_show"))
 		return
 	}
 	c.Data["File"] = diff.Files[0]
 
-	c.HTML(200, EDIT_DIFF_PREVIEW)
+	c.Success(EDIT_DIFF_PREVIEW)
 }
 
 func DeleteFile(c *context.Context) {
@@ -468,7 +468,7 @@ func UploadFilePost(c *context.Context, f form.UploadRepoFile) {
 				break
 			}
 
-			c.ServerError("GetTreeEntryByPath", err)
+			c.Error(err, "get tree entry")
 			return
 		}
 
@@ -514,7 +514,7 @@ func UploadFilePost(c *context.Context, f form.UploadRepoFile) {
 func UploadFileToServer(c *context.Context) {
 	file, header, err := c.Req.FormFile("file")
 	if err != nil {
-		c.Error(http.StatusInternalServerError, fmt.Sprintf("FormFile: %v", err))
+		c.Error(err, "get file")
 		return
 	}
 	defer file.Close()
@@ -537,14 +537,14 @@ func UploadFileToServer(c *context.Context) {
 		}
 
 		if !allowed {
-			c.Error(http.StatusBadRequest, ErrFileTypeForbidden.Error())
+			c.PlainText(http.StatusBadRequest, ErrFileTypeForbidden.Error())
 			return
 		}
 	}
 
 	upload, err := db.NewUpload(header.Filename, buf, file)
 	if err != nil {
-		c.Error(http.StatusInternalServerError, fmt.Sprintf("NewUpload: %v", err))
+		c.Error(err, "new upload")
 		return
 	}
 
@@ -556,15 +556,15 @@ func UploadFileToServer(c *context.Context) {
 
 func RemoveUploadFileFromServer(c *context.Context, f form.RemoveUploadFile) {
 	if len(f.File) == 0 {
-		c.Status(204)
+		c.Status(http.StatusNoContent)
 		return
 	}
 
 	if err := db.DeleteUploadByUUID(f.File); err != nil {
-		c.Error(500, fmt.Sprintf("DeleteUploadByUUID: %v", err))
+		c.Error(err, "delete upload by UUID")
 		return
 	}
 
 	log.Trace("Upload file removed: %s", f.File)
-	c.Status(204)
+	c.Status(http.StatusNoContent)
 }

+ 10 - 11
internal/route/repo/http.go

@@ -22,7 +22,6 @@ import (
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
 	"gogs.io/gogs/internal/lazyregexp"
 	"gogs.io/gogs/internal/tool"
 )
@@ -39,7 +38,7 @@ type HTTPContext struct {
 // askCredentials responses HTTP header and status which informs client to provide credentials.
 func askCredentials(c *context.Context, status int, text string) {
 	c.Resp.Header().Set("WWW-Authenticate", "Basic realm=\".\"")
-	c.HandleText(status, text)
+	c.PlainText(status, text)
 }
 
 func HTTPContexter() macaron.Handler {
@@ -66,13 +65,13 @@ func HTTPContexter() macaron.Handler {
 
 		owner, err := db.GetUserByName(ownerName)
 		if err != nil {
-			c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
+			c.NotFoundOrError(err, "get user by name")
 			return
 		}
 
 		repo, err := db.GetRepositoryByName(owner.ID, repoName)
 		if err != nil {
-			c.NotFoundOrServerError("GetRepositoryByName", errors.IsRepoNotExist, err)
+			c.NotFoundOrError(err, "get repository by name")
 			return
 		}
 
@@ -113,8 +112,8 @@ func HTTPContexter() macaron.Handler {
 		}
 
 		authUser, err := db.UserLogin(authUsername, authPassword, -1)
-		if err != nil && !errors.IsUserNotExist(err) {
-			c.Handle(http.StatusInternalServerError, "UserLogin", err)
+		if err != nil && !db.IsErrUserNotExist(err) {
+			c.Error(err, "authenticate user")
 			return
 		}
 
@@ -125,7 +124,7 @@ func HTTPContexter() macaron.Handler {
 				if db.IsErrAccessTokenEmpty(err) || db.IsErrAccessTokenNotExist(err) {
 					askCredentials(c, http.StatusUnauthorized, "")
 				} else {
-					c.Handle(http.StatusInternalServerError, "GetAccessTokenBySHA", err)
+					c.Error(err, "get access token by SHA")
 				}
 				return
 			}
@@ -136,7 +135,7 @@ func HTTPContexter() macaron.Handler {
 			if err != nil {
 				// Once we found token, we're supposed to find its related user,
 				// thus any error is unexpected.
-				c.Handle(http.StatusInternalServerError, "GetUserByID", err)
+				c.Error(err, "get user by ID")
 				return
 			}
 		} else if authUser.IsEnabledTwoFactor() {
@@ -153,7 +152,7 @@ Please create and use personal access token on user settings page`)
 		}
 		has, err := db.HasAccess(authUser.ID, repo, mode)
 		if err != nil {
-			c.Handle(http.StatusInternalServerError, "HasAccess", err)
+			c.Error(err, "check access")
 			return
 		} else if !has {
 			askCredentials(c, http.StatusForbidden, "User permission denied")
@@ -161,7 +160,7 @@ Please create and use personal access token on user settings page`)
 		}
 
 		if !isPull && repo.IsMirror {
-			c.HandleText(http.StatusForbidden, "Mirror repository is read-only")
+			c.PlainText(http.StatusForbidden, "Mirror repository is read-only")
 			return
 		}
 
@@ -388,7 +387,7 @@ func HTTP(c *HTTPContext) {
 		// but we only want to output this message only if user is really trying to access
 		// Git HTTP endpoints.
 		if conf.Repository.DisableHTTPGit {
-			c.HandleText(http.StatusForbidden, "Interacting with repositories by HTTP protocol is not disabled")
+			c.PlainText(http.StatusForbidden, "Interacting with repositories by HTTP protocol is disabled")
 			return
 		}
 

+ 79 - 100
internal/route/repo/issue.go

@@ -51,7 +51,7 @@ var (
 
 func MustEnableIssues(c *context.Context) {
 	if !c.Repo.Repository.EnableIssues {
-		c.Handle(404, "MustEnableIssues", nil)
+		c.NotFound()
 		return
 	}
 
@@ -63,7 +63,7 @@ func MustEnableIssues(c *context.Context) {
 
 func MustAllowPulls(c *context.Context) {
 	if !c.Repo.Repository.AllowsPulls() {
-		c.Handle(404, "MustAllowPulls", nil)
+		c.NotFound()
 		return
 	}
 
@@ -77,7 +77,7 @@ func MustAllowPulls(c *context.Context) {
 func RetrieveLabels(c *context.Context) {
 	labels, err := db.GetLabelsByRepoID(c.Repo.Repository.ID)
 	if err != nil {
-		c.Handle(500, "RetrieveLabels.GetLabels", err)
+		c.Error(err, "get labels by repository ID")
 		return
 	}
 	for _, l := range labels {
@@ -182,14 +182,14 @@ func issues(c *context.Context, isPullList bool) {
 		SortType:    sortType,
 	})
 	if err != nil {
-		c.Handle(500, "Issues", err)
+		c.Error(err, "list issues")
 		return
 	}
 
 	// Get issue-user relations.
 	pairs, err := db.GetIssueUsers(repo.ID, posterID, isShowClosed)
 	if err != nil {
-		c.Handle(500, "GetIssueUsers", err)
+		c.Error(err, "get issue-user relations")
 		return
 	}
 
@@ -213,14 +213,14 @@ func issues(c *context.Context, isPullList bool) {
 	// Get milestones.
 	c.Data["Milestones"], err = db.GetMilestonesByRepoID(repo.ID)
 	if err != nil {
-		c.Handle(500, "GetAllRepoMilestones", err)
+		c.Error(err, "get milestone by repository ID")
 		return
 	}
 
 	// Get assignees.
 	c.Data["Assignees"], err = repo.GetAssignees()
 	if err != nil {
-		c.Handle(500, "GetAssignees", err)
+		c.Error(err, "get assignees")
 		return
 	}
 
@@ -241,7 +241,7 @@ func issues(c *context.Context, isPullList bool) {
 		c.Data["State"] = "open"
 	}
 
-	c.HTML(200, ISSUES)
+	c.Success(ISSUES)
 }
 
 func Issues(c *context.Context) {
@@ -264,18 +264,18 @@ func RetrieveRepoMilestonesAndAssignees(c *context.Context, repo *db.Repository)
 	var err error
 	c.Data["OpenMilestones"], err = db.GetMilestones(repo.ID, -1, false)
 	if err != nil {
-		c.Handle(500, "GetMilestones", err)
+		c.Error(err, "get open milestones")
 		return
 	}
 	c.Data["ClosedMilestones"], err = db.GetMilestones(repo.ID, -1, true)
 	if err != nil {
-		c.Handle(500, "GetMilestones", err)
+		c.Error(err, "get closed milestones")
 		return
 	}
 
 	c.Data["Assignees"], err = repo.GetAssignees()
 	if err != nil {
-		c.Handle(500, "GetAssignees", err)
+		c.Error(err, "get assignees")
 		return
 	}
 }
@@ -287,7 +287,7 @@ func RetrieveRepoMetas(c *context.Context, repo *db.Repository) []*db.Label {
 
 	labels, err := db.GetLabelsByRepoID(repo.ID)
 	if err != nil {
-		c.Handle(500, "GetLabelsByRepoID", err)
+		c.Error(err, "get labels by repository ID")
 		return nil
 	}
 	c.Data["Labels"] = labels
@@ -345,7 +345,7 @@ func NewIssue(c *context.Context) {
 		return
 	}
 
-	c.HTML(200, ISSUE_NEW)
+	c.Success(ISSUE_NEW)
 }
 
 func ValidateRepoMetas(c *context.Context, f form.NewIssue) ([]int64, int64, int64) {
@@ -382,7 +382,7 @@ func ValidateRepoMetas(c *context.Context, f form.NewIssue) ([]int64, int64, int
 	if milestoneID > 0 {
 		c.Data["Milestone"], err = repo.GetMilestoneByID(milestoneID)
 		if err != nil {
-			c.Handle(500, "GetMilestoneByID", err)
+			c.Error(err, "get milestone by ID")
 			return nil, 0, 0
 		}
 		c.Data["milestone_id"] = milestoneID
@@ -393,7 +393,7 @@ func ValidateRepoMetas(c *context.Context, f form.NewIssue) ([]int64, int64, int
 	if assigneeID > 0 {
 		c.Data["Assignee"], err = repo.GetAssigneeByID(assigneeID)
 		if err != nil {
-			c.Handle(500, "GetAssigneeByID", err)
+			c.Error(err, "get assignee by ID")
 			return nil, 0, 0
 		}
 		c.Data["assignee_id"] = assigneeID
@@ -415,7 +415,7 @@ func NewIssuePost(c *context.Context, f form.NewIssue) {
 	}
 
 	if c.HasError() {
-		c.HTML(200, ISSUE_NEW)
+		c.Success(ISSUE_NEW)
 		return
 	}
 
@@ -434,7 +434,7 @@ func NewIssuePost(c *context.Context, f form.NewIssue) {
 		Content:     f.Content,
 	}
 	if err := db.NewIssue(c.Repo.Repository, issue, labelIDs, attachments); err != nil {
-		c.Handle(500, "NewIssue", err)
+		c.Error(err, "new issue")
 		return
 	}
 
@@ -445,7 +445,7 @@ func NewIssuePost(c *context.Context, f form.NewIssue) {
 func uploadAttachment(c *context.Context, allowedTypes []string) {
 	file, header, err := c.Req.FormFile("file")
 	if err != nil {
-		c.Error(500, fmt.Sprintf("FormFile: %v", err))
+		c.Error(err, "get file")
 		return
 	}
 	defer file.Close()
@@ -467,18 +467,18 @@ func uploadAttachment(c *context.Context, allowedTypes []string) {
 	}
 
 	if !allowed {
-		c.Error(400, ErrFileTypeForbidden.Error())
+		c.PlainText(http.StatusBadRequest, ErrFileTypeForbidden.Error())
 		return
 	}
 
 	attach, err := db.NewAttachment(header.Filename, buf, file)
 	if err != nil {
-		c.Error(500, fmt.Sprintf("NewAttachment: %v", err))
+		c.Error(err, "new attachment")
 		return
 	}
 
 	log.Trace("New attachment uploaded: %s", attach.UUID)
-	c.JSON(200, map[string]string{
+	c.JSONSuccess(map[string]string{
 		"uuid": attach.UUID,
 	})
 }
@@ -505,7 +505,7 @@ func viewIssue(c *context.Context, isPullList bool) {
 
 	issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, index)
 	if err != nil {
-		c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
+		c.NotFoundOrError(err, "get issue by index")
 		return
 	}
 	c.Data["Title"] = issue.Title
@@ -559,7 +559,7 @@ func viewIssue(c *context.Context, isPullList bool) {
 	}
 	labels, err := db.GetLabelsByRepoID(repo.ID)
 	if err != nil {
-		c.Handle(500, "GetLabelsByRepoID", err)
+		c.Error(err, "get labels by repository ID")
 		return
 	}
 	hasSelected := false
@@ -583,7 +583,7 @@ func viewIssue(c *context.Context, isPullList bool) {
 	if c.IsLogged {
 		// Update issue-user.
 		if err = issue.ReadBy(c.User.ID); err != nil {
-			c.Handle(500, "ReadBy", err)
+			c.Error(err, "mark read by")
 			return
 		}
 	}
@@ -638,8 +638,8 @@ func viewIssue(c *context.Context, isPullList bool) {
 		branchProtected := false
 		protectBranch, err := db.GetProtectBranchOfRepoByName(pull.BaseRepoID, pull.HeadBranch)
 		if err != nil {
-			if !errors.IsErrBranchNotExist(err) {
-				c.ServerError("GetProtectBranchOfRepoByName", err)
+			if !db.IsErrBranchNotExist(err) {
+				c.Error(err, "get protect branch of repository by name")
 				return
 			}
 		} else {
@@ -661,7 +661,7 @@ func viewIssue(c *context.Context, isPullList bool) {
 	c.Data["Issue"] = issue
 	c.Data["IsIssueOwner"] = c.Repo.IsWriter() || (c.IsLogged && issue.IsPoster(c.User.ID))
 	c.Data["SignInLink"] = conf.Server.Subpath + "/user/login?redirect_to=" + c.Data["Link"].(string)
-	c.HTML(200, ISSUE_VIEW)
+	c.Success(ISSUE_VIEW)
 }
 
 func ViewIssue(c *context.Context) {
@@ -675,7 +675,7 @@ func ViewPull(c *context.Context) {
 func getActionIssue(c *context.Context) *db.Issue {
 	issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
 	if err != nil {
-		c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
+		c.NotFoundOrError(err, "get issue by index")
 		return nil
 	}
 
@@ -695,22 +695,22 @@ func UpdateIssueTitle(c *context.Context) {
 	}
 
 	if !c.IsLogged || (!issue.IsPoster(c.User.ID) && !c.Repo.IsWriter()) {
-		c.Error(403)
+		c.Status(http.StatusForbidden)
 		return
 	}
 
 	title := c.QueryTrim("title")
 	if len(title) == 0 {
-		c.Error(204)
+		c.Status(http.StatusNoContent)
 		return
 	}
 
 	if err := issue.ChangeTitle(c.User, title); err != nil {
-		c.Handle(500, "ChangeTitle", err)
+		c.Error(err, "change title")
 		return
 	}
 
-	c.JSON(200, map[string]interface{}{
+	c.JSONSuccess(map[string]interface{}{
 		"title": issue.Title,
 	})
 }
@@ -722,17 +722,17 @@ func UpdateIssueContent(c *context.Context) {
 	}
 
 	if !c.IsLogged || (c.User.ID != issue.PosterID && !c.Repo.IsWriter()) {
-		c.Error(403)
+		c.Status(http.StatusForbidden)
 		return
 	}
 
 	content := c.Query("content")
 	if err := issue.ChangeContent(c.User, content); err != nil {
-		c.Handle(500, "ChangeContent", err)
+		c.Error(err, "change content")
 		return
 	}
 
-	c.JSON(200, map[string]string{
+	c.JSONSuccess(map[string]string{
 		"content": string(markup.Markdown(issue.Content, c.Query("context"), c.Repo.Repository.ComposeMetas())),
 	})
 }
@@ -745,35 +745,31 @@ func UpdateIssueLabel(c *context.Context) {
 
 	if c.Query("action") == "clear" {
 		if err := issue.ClearLabels(c.User); err != nil {
-			c.Handle(500, "ClearLabels", err)
+			c.Error(err, "clear labels")
 			return
 		}
 	} else {
 		isAttach := c.Query("action") == "attach"
 		label, err := db.GetLabelOfRepoByID(c.Repo.Repository.ID, c.QueryInt64("id"))
 		if err != nil {
-			if db.IsErrLabelNotExist(err) {
-				c.Error(404, "GetLabelByID")
-			} else {
-				c.Handle(500, "GetLabelByID", err)
-			}
+			c.NotFoundOrError(err, "get label by ID")
 			return
 		}
 
 		if isAttach && !issue.HasLabel(label.ID) {
 			if err = issue.AddLabel(c.User, label); err != nil {
-				c.Handle(500, "AddLabel", err)
+				c.Error(err, "add label")
 				return
 			}
 		} else if !isAttach && issue.HasLabel(label.ID) {
 			if err = issue.RemoveLabel(c.User, label); err != nil {
-				c.Handle(500, "RemoveLabel", err)
+				c.Error(err, "remove label")
 				return
 			}
 		}
 	}
 
-	c.JSON(200, map[string]interface{}{
+	c.JSONSuccess(map[string]interface{}{
 		"ok": true,
 	})
 }
@@ -787,7 +783,7 @@ func UpdateIssueMilestone(c *context.Context) {
 	oldMilestoneID := issue.MilestoneID
 	milestoneID := c.QueryInt64("id")
 	if oldMilestoneID == milestoneID {
-		c.JSON(200, map[string]interface{}{
+		c.JSONSuccess(map[string]interface{}{
 			"ok": true,
 		})
 		return
@@ -796,11 +792,11 @@ func UpdateIssueMilestone(c *context.Context) {
 	// Not check for invalid milestone id and give responsibility to owners.
 	issue.MilestoneID = milestoneID
 	if err := db.ChangeMilestoneAssign(c.User, issue, oldMilestoneID); err != nil {
-		c.Handle(500, "ChangeMilestoneAssign", err)
+		c.Error(err, "change milestone assign")
 		return
 	}
 
-	c.JSON(200, map[string]interface{}{
+	c.JSONSuccess(map[string]interface{}{
 		"ok": true,
 	})
 }
@@ -813,18 +809,18 @@ func UpdateIssueAssignee(c *context.Context) {
 
 	assigneeID := c.QueryInt64("id")
 	if issue.AssigneeID == assigneeID {
-		c.JSON(200, map[string]interface{}{
+		c.JSONSuccess(map[string]interface{}{
 			"ok": true,
 		})
 		return
 	}
 
 	if err := issue.ChangeAssignee(c.User, assigneeID); err != nil {
-		c.Handle(500, "ChangeAssignee", err)
+		c.Error(err, "change assignee")
 		return
 	}
 
-	c.JSON(200, map[string]interface{}{
+	c.JSONSuccess(map[string]interface{}{
 		"ok": true,
 	})
 }
@@ -862,7 +858,7 @@ func NewComment(c *context.Context, f form.CreateComment) {
 				pr, err = db.GetUnmergedPullRequest(pull.HeadRepoID, pull.BaseRepoID, pull.HeadBranch, pull.BaseBranch)
 				if err != nil {
 					if !db.IsErrPullRequestNotExist(err) {
-						c.ServerError("GetUnmergedPullRequest", err)
+						c.Error(err, "get unmerged pull request")
 						return
 					}
 				}
@@ -870,7 +866,7 @@ func NewComment(c *context.Context, f form.CreateComment) {
 				// Regenerate patch and test conflict.
 				if pr == nil {
 					if err = issue.PullRequest.UpdatePatch(); err != nil {
-						c.ServerError("UpdatePatch", err)
+						c.Error(err, "update patch")
 						return
 					}
 
@@ -913,7 +909,7 @@ func NewComment(c *context.Context, f form.CreateComment) {
 
 	comment, err = db.CreateIssueComment(c.User, c.Repo.Repository, issue, f.Content, attachments)
 	if err != nil {
-		c.ServerError("CreateIssueComment", err)
+		c.Error(err, "create issue comment")
 		return
 	}
 
@@ -923,32 +919,32 @@ func NewComment(c *context.Context, f form.CreateComment) {
 func UpdateCommentContent(c *context.Context) {
 	comment, err := db.GetCommentByID(c.ParamsInt64(":id"))
 	if err != nil {
-		c.NotFoundOrServerError("GetCommentByID", db.IsErrCommentNotExist, err)
+		c.NotFoundOrError(err, "get comment by ID")
 		return
 	}
 
 	if c.UserID() != comment.PosterID && !c.Repo.IsAdmin() {
-		c.Error(404)
+		c.NotFound()
 		return
 	} else if comment.Type != db.COMMENT_TYPE_COMMENT {
-		c.Error(204)
+		c.Status(http.StatusNoContent)
 		return
 	}
 
 	oldContent := comment.Content
 	comment.Content = c.Query("content")
 	if len(comment.Content) == 0 {
-		c.JSON(200, map[string]interface{}{
+		c.JSONSuccess(map[string]interface{}{
 			"content": "",
 		})
 		return
 	}
 	if err = db.UpdateComment(c.User, comment, oldContent); err != nil {
-		c.Handle(500, "UpdateComment", err)
+		c.Error(err, "update comment")
 		return
 	}
 
-	c.JSON(200, map[string]string{
+	c.JSONSuccess(map[string]string{
 		"content": string(markup.Markdown(comment.Content, c.Query("context"), c.Repo.Repository.ComposeMetas())),
 	})
 }
@@ -956,24 +952,24 @@ func UpdateCommentContent(c *context.Context) {
 func DeleteComment(c *context.Context) {
 	comment, err := db.GetCommentByID(c.ParamsInt64(":id"))
 	if err != nil {
-		c.NotFoundOrServerError("GetCommentByID", db.IsErrCommentNotExist, err)
+		c.NotFoundOrError(err, "get comment by ID")
 		return
 	}
 
 	if c.UserID() != comment.PosterID && !c.Repo.IsAdmin() {
-		c.Error(404)
+		c.NotFound()
 		return
 	} else if comment.Type != db.COMMENT_TYPE_COMMENT {
-		c.Error(204)
+		c.Status(http.StatusNoContent)
 		return
 	}
 
 	if err = db.DeleteCommentByID(c.User, comment.ID); err != nil {
-		c.Handle(500, "DeleteCommentByID", err)
+		c.Error(err, "delete comment by ID")
 		return
 	}
 
-	c.Status(200)
+	c.Status(http.StatusOK)
 }
 
 func Labels(c *context.Context) {
@@ -982,7 +978,7 @@ func Labels(c *context.Context) {
 	c.Data["PageIsLabels"] = true
 	c.Data["RequireMinicolors"] = true
 	c.Data["LabelTemplates"] = db.LabelTemplates
-	c.HTML(200, LABELS)
+	c.Success(LABELS)
 }
 
 func InitializeLabels(c *context.Context, f form.InitializeLabels) {
@@ -1006,7 +1002,7 @@ func InitializeLabels(c *context.Context, f form.InitializeLabels) {
 		}
 	}
 	if err := db.NewLabels(labels...); err != nil {
-		c.Handle(500, "NewLabels", err)
+		c.Error(err, "new labels")
 		return
 	}
 	c.RawRedirect(c.Repo.MakeURL("labels"))
@@ -1028,7 +1024,7 @@ func NewLabel(c *context.Context, f form.CreateLabel) {
 		Color:  f.Color,
 	}
 	if err := db.NewLabels(l); err != nil {
-		c.Handle(500, "NewLabel", err)
+		c.Error(err, "new labels")
 		return
 	}
 	c.RawRedirect(c.Repo.MakeURL("labels"))
@@ -1037,19 +1033,14 @@ func NewLabel(c *context.Context, f form.CreateLabel) {
 func UpdateLabel(c *context.Context, f form.CreateLabel) {
 	l, err := db.GetLabelByID(f.ID)
 	if err != nil {
-		switch {
-		case db.IsErrLabelNotExist(err):
-			c.Error(404)
-		default:
-			c.Handle(500, "UpdateLabel", err)
-		}
+		c.NotFoundOrError(err, "get label by ID")
 		return
 	}
 
 	l.Name = f.Title
 	l.Color = f.Color
 	if err := db.UpdateLabel(l); err != nil {
-		c.Handle(500, "UpdateLabel", err)
+		c.Error(err, "update label")
 		return
 	}
 	c.RawRedirect(c.Repo.MakeURL("labels"))
@@ -1092,7 +1083,7 @@ func Milestones(c *context.Context) {
 
 	miles, err := db.GetMilestones(c.Repo.Repository.ID, page, isShowClosed)
 	if err != nil {
-		c.Handle(500, "GetMilestones", err)
+		c.Error(err, "get milestones")
 		return
 	}
 	for _, m := range miles {
@@ -1112,7 +1103,7 @@ func Milestones(c *context.Context) {
 	}
 
 	c.Data["IsShowClosed"] = isShowClosed
-	c.HTML(200, MILESTONE)
+	c.Success(MILESTONE)
 }
 
 func NewMilestone(c *context.Context) {
@@ -1121,7 +1112,7 @@ func NewMilestone(c *context.Context) {
 	c.Data["PageIsMilestones"] = true
 	c.Data["RequireDatetimepicker"] = true
 	c.Data["DateLang"] = conf.I18n.DateLang(c.Locale.Language())
-	c.HTML(200, MILESTONE_NEW)
+	c.Success(MILESTONE_NEW)
 }
 
 func NewMilestonePost(c *context.Context, f form.CreateMilestone) {
@@ -1132,7 +1123,7 @@ func NewMilestonePost(c *context.Context, f form.CreateMilestone) {
 	c.Data["DateLang"] = conf.I18n.DateLang(c.Locale.Language())
 
 	if c.HasError() {
-		c.HTML(200, MILESTONE_NEW)
+		c.Success(MILESTONE_NEW)
 		return
 	}
 
@@ -1152,7 +1143,7 @@ func NewMilestonePost(c *context.Context, f form.CreateMilestone) {
 		Content:  f.Content,
 		Deadline: deadline,
 	}); err != nil {
-		c.Handle(500, "NewMilestone", err)
+		c.Error(err, "new milestone")
 		return
 	}
 
@@ -1169,11 +1160,7 @@ func EditMilestone(c *context.Context) {
 
 	m, err := db.GetMilestoneByRepoID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
 	if err != nil {
-		if db.IsErrMilestoneNotExist(err) {
-			c.Handle(404, "", nil)
-		} else {
-			c.Handle(500, "GetMilestoneByRepoID", err)
-		}
+		c.NotFoundOrError(err, "get milestone by repository ID")
 		return
 	}
 	c.Data["title"] = m.Name
@@ -1181,7 +1168,7 @@ func EditMilestone(c *context.Context) {
 	if len(m.DeadlineString) > 0 {
 		c.Data["deadline"] = m.DeadlineString
 	}
-	c.HTML(200, MILESTONE_NEW)
+	c.Success(MILESTONE_NEW)
 }
 
 func EditMilestonePost(c *context.Context, f form.CreateMilestone) {
@@ -1192,7 +1179,7 @@ func EditMilestonePost(c *context.Context, f form.CreateMilestone) {
 	c.Data["DateLang"] = conf.I18n.DateLang(c.Locale.Language())
 
 	if c.HasError() {
-		c.HTML(200, MILESTONE_NEW)
+		c.Success(MILESTONE_NEW)
 		return
 	}
 
@@ -1208,18 +1195,14 @@ func EditMilestonePost(c *context.Context, f form.CreateMilestone) {
 
 	m, err := db.GetMilestoneByRepoID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
 	if err != nil {
-		if db.IsErrMilestoneNotExist(err) {
-			c.Handle(404, "", nil)
-		} else {
-			c.Handle(500, "GetMilestoneByRepoID", err)
-		}
+		c.NotFoundOrError(err, "get milestone by repository ID")
 		return
 	}
 	m.Name = f.Title
 	m.Content = f.Content
 	m.Deadline = deadline
 	if err = db.UpdateMilestone(m); err != nil {
-		c.Handle(500, "UpdateMilestone", err)
+		c.Error(err, "update milestone")
 		return
 	}
 
@@ -1230,11 +1213,7 @@ func EditMilestonePost(c *context.Context, f form.CreateMilestone) {
 func ChangeMilestonStatus(c *context.Context) {
 	m, err := db.GetMilestoneByRepoID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
 	if err != nil {
-		if db.IsErrMilestoneNotExist(err) {
-			c.Handle(404, "", err)
-		} else {
-			c.Handle(500, "GetMilestoneByRepoID", err)
-		}
+		c.NotFoundOrError(err, "get milestone by repository ID")
 		return
 	}
 
@@ -1246,7 +1225,7 @@ func ChangeMilestonStatus(c *context.Context) {
 	case "open":
 		if m.IsClosed {
 			if err = db.ChangeMilestoneStatus(m, false); err != nil {
-				c.Handle(500, "ChangeMilestoneStatus", err)
+				c.Error(err, "change milestone status to open")
 				return
 			}
 		}
@@ -1255,7 +1234,7 @@ func ChangeMilestonStatus(c *context.Context) {
 		if !m.IsClosed {
 			m.ClosedDate = time.Now()
 			if err = db.ChangeMilestoneStatus(m, true); err != nil {
-				c.Handle(500, "ChangeMilestoneStatus", err)
+				c.Error(err, "change milestone status to closed")
 				return
 			}
 		}
@@ -1272,7 +1251,7 @@ func DeleteMilestone(c *context.Context) {
 		c.Flash.Success(c.Tr("repo.milestones.deletion_success"))
 	}
 
-	c.JSON(200, map[string]interface{}{
+	c.JSONSuccess(map[string]interface{}{
 		"redirect": c.Repo.MakeURL("milestones"),
 	})
 }

+ 42 - 42
internal/route/repo/pull.go

@@ -5,6 +5,7 @@
 package repo
 
 import (
+	"net/http"
 	"path"
 	"strings"
 
@@ -16,7 +17,6 @@ import (
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
 	"gogs.io/gogs/internal/form"
 	"gogs.io/gogs/internal/gitutil"
 	"gogs.io/gogs/internal/tool"
@@ -49,7 +49,7 @@ var (
 func parseBaseRepository(c *context.Context) *db.Repository {
 	baseRepo, err := db.GetRepositoryByID(c.ParamsInt64(":repoid"))
 	if err != nil {
-		c.NotFoundOrServerError("GetRepositoryByID", errors.IsRepoNotExist, err)
+		c.NotFoundOrError(err, "get repository by ID")
 		return nil
 	}
 
@@ -63,13 +63,13 @@ func parseBaseRepository(c *context.Context) *db.Repository {
 	c.Data["IsPrivate"] = baseRepo.IsPrivate
 
 	if err = baseRepo.GetOwner(); err != nil {
-		c.ServerError("GetOwner", err)
+		c.Error(err, "get owner")
 		return nil
 	}
 	c.Data["ForkFrom"] = baseRepo.Owner.Name + "/" + baseRepo.Name
 
 	if err := c.User.GetOrganizations(true); err != nil {
-		c.ServerError("GetOrganizations", err)
+		c.Error(err, "get organizations")
 		return nil
 	}
 	c.Data["Orgs"] = c.User.Orgs
@@ -110,7 +110,7 @@ func ForkPost(c *context.Context, f form.CreateRepo) {
 
 	repo, has, err := db.HasForkedRepo(ctxUser.ID, baseRepo.ID)
 	if err != nil {
-		c.ServerError("HasForkedRepo", err)
+		c.Error(err, "check forked repository")
 		return
 	} else if has {
 		c.Redirect(repo.Link())
@@ -119,7 +119,7 @@ func ForkPost(c *context.Context, f form.CreateRepo) {
 
 	// Check ownership of organization.
 	if ctxUser.IsOrganization() && !ctxUser.IsOwnedBy(c.User.ID) {
-		c.Error(403)
+		c.Status(http.StatusForbidden)
 		return
 	}
 
@@ -133,7 +133,7 @@ func ForkPost(c *context.Context, f form.CreateRepo) {
 	if err != nil {
 		c.Data["Err_RepoName"] = true
 		switch {
-		case errors.IsReachLimitOfRepo(err):
+		case db.IsErrReachLimitOfRepo(err):
 			c.RenderWithErr(c.Tr("repo.form.reach_limit_of_creation", c.User.RepoCreationNum()), FORK, &f)
 		case db.IsErrRepoAlreadyExist(err):
 			c.RenderWithErr(c.Tr("repo.settings.new_owner_has_same_repo"), FORK, &f)
@@ -142,7 +142,7 @@ func ForkPost(c *context.Context, f form.CreateRepo) {
 		case db.IsErrNamePatternNotAllowed(err):
 			c.RenderWithErr(c.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), FORK, &f)
 		default:
-			c.ServerError("ForkPost", err)
+			c.Error(err, "fork repository")
 		}
 		return
 	}
@@ -154,21 +154,21 @@ func ForkPost(c *context.Context, f form.CreateRepo) {
 func checkPullInfo(c *context.Context) *db.Issue {
 	issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
 	if err != nil {
-		c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
+		c.NotFoundOrError(err, "get issue by index")
 		return nil
 	}
 	c.Data["Title"] = issue.Title
 	c.Data["Issue"] = issue
 
 	if !issue.IsPull {
-		c.Handle(404, "ViewPullCommits", nil)
+		c.NotFound()
 		return nil
 	}
 
 	if c.IsLogged {
 		// Update issue-user.
 		if err = issue.ReadBy(c.User.ID); err != nil {
-			c.ServerError("ReadBy", err)
+			c.Error(err, "mark read by")
 			return nil
 		}
 	}
@@ -185,14 +185,14 @@ func PrepareMergedViewPullInfo(c *context.Context, issue *db.Issue) {
 	var err error
 	c.Data["NumCommits"], err = c.Repo.GitRepo.RevListCount([]string{pull.MergeBase + "..." + pull.MergedCommitID})
 	if err != nil {
-		c.ServerError("Repo.GitRepo.CommitsCountBetween", err)
+		c.Error(err, "count commits")
 		return
 	}
 
 	names, err := c.Repo.GitRepo.DiffNameOnly(pull.MergeBase, pull.MergedCommitID, git.DiffNameOnlyOptions{NeedsMergeBase: true})
 	c.Data["NumFiles"] = len(names)
 	if err != nil {
-		c.ServerError("Repo.GitRepo.FilesCountBetween", err)
+		c.Error(err, "get changed files")
 		return
 	}
 }
@@ -212,7 +212,7 @@ func PrepareViewPullInfo(c *context.Context, issue *db.Issue) *gitutil.PullReque
 	if pull.HeadRepo != nil {
 		headGitRepo, err = git.Open(pull.HeadRepo.RepoPath())
 		if err != nil {
-			c.ServerError("open repository", err)
+			c.Error(err, "open repository")
 			return nil
 		}
 	}
@@ -236,7 +236,7 @@ func PrepareViewPullInfo(c *context.Context, issue *db.Issue) *gitutil.PullReque
 			return nil
 		}
 
-		c.ServerError("GetPullRequestInfo", err)
+		c.Error(err, "get pull request meta")
 		return nil
 	}
 	c.Data["NumCommits"] = len(prMeta.Commits)
@@ -267,17 +267,17 @@ func ViewPullCommits(c *context.Context) {
 		}
 		startCommit, err := c.Repo.GitRepo.CatFileCommit(pull.MergeBase)
 		if err != nil {
-			c.ServerError("get commit of merge base", err)
+			c.Error(err, "get commit of merge base")
 			return
 		}
 		endCommit, err := c.Repo.GitRepo.CatFileCommit(pull.MergedCommitID)
 		if err != nil {
-			c.ServerError("get merged commit", err)
+			c.Error(err, "get merged commit")
 			return
 		}
 		commits, err = c.Repo.GitRepo.RevList([]string{startCommit.ID.String() + "..." + endCommit.ID.String()})
 		if err != nil {
-			c.ServerError("list commits", err)
+			c.Error(err, "list commits")
 			return
 		}
 
@@ -330,7 +330,7 @@ func ViewPullFiles(c *context.Context) {
 		if c.Written() {
 			return
 		} else if prInfo == nil {
-			c.Handle(404, "ViewPullFiles", nil)
+			c.NotFound()
 			return
 		}
 
@@ -338,13 +338,13 @@ func ViewPullFiles(c *context.Context) {
 
 		headGitRepo, err := git.Open(headRepoPath)
 		if err != nil {
-			c.ServerError("open repository", err)
+			c.Error(err, "open repository")
 			return
 		}
 
 		headCommitID, err := headGitRepo.BranchCommitID(pull.HeadBranch)
 		if err != nil {
-			c.ServerError("get head branch commit ID", err)
+			c.Error(err, "get head branch commit ID")
 			return
 		}
 
@@ -359,7 +359,7 @@ func ViewPullFiles(c *context.Context) {
 		git.DiffOptions{Base: startCommitID},
 	)
 	if err != nil {
-		c.ServerError("get diff", err)
+		c.Error(err, "get diff")
 		return
 	}
 	c.Data["Diff"] = diff
@@ -367,7 +367,7 @@ func ViewPullFiles(c *context.Context) {
 
 	commit, err := gitRepo.CatFileCommit(endCommitID)
 	if err != nil {
-		c.ServerError("get commit", err)
+		c.Error(err, "get commit")
 		return
 	}
 
@@ -406,7 +406,7 @@ func MergePullRequest(c *context.Context) {
 
 	pr, err := db.GetPullRequestByIssueID(issue.ID)
 	if err != nil {
-		c.NotFoundOrServerError("GetPullRequestByIssueID", db.IsErrPullRequestNotExist, err)
+		c.NotFoundOrError(err, "get pull request by issue ID")
 		return
 	}
 
@@ -418,7 +418,7 @@ func MergePullRequest(c *context.Context) {
 	pr.Issue = issue
 	pr.Issue.Repo = c.Repo.Repository
 	if err = pr.Merge(c.User, c.Repo.GitRepo, db.MergeStyle(c.Query("merge_style")), c.Query("commit_description")); err != nil {
-		c.ServerError("Merge", err)
+		c.Error(err, "merge")
 		return
 	}
 
@@ -460,7 +460,7 @@ func ParseCompareInfo(c *context.Context) (*db.User, *db.Repository, *git.Reposi
 	} else if len(headInfos) == 2 {
 		headUser, err = db.GetUserByName(headInfos[0])
 		if err != nil {
-			c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
+			c.NotFoundOrError(err, "get user by name")
 			return nil, nil, nil, nil, "", ""
 		}
 		headBranch = headInfos[1]
@@ -491,7 +491,7 @@ func ParseCompareInfo(c *context.Context) (*db.User, *db.Repository, *git.Reposi
 		var has bool
 		headRepo, has, err = db.HasForkedRepo(headUser.ID, baseRepo.ID)
 		if err != nil {
-			c.ServerError("HasForkedRepo", err)
+			c.Error(err, "get forked repository")
 			return nil, nil, nil, nil, "", ""
 		} else if !has {
 			log.Trace("ParseCompareInfo [base_repo_id: %d]: does not have fork or in same repository", baseRepo.ID)
@@ -501,7 +501,7 @@ func ParseCompareInfo(c *context.Context) (*db.User, *db.Repository, *git.Reposi
 
 		headGitRepo, err = git.Open(db.RepoPath(headUser.Name, headRepo.Name))
 		if err != nil {
-			c.ServerError("open repository", err)
+			c.Error(err, "open repository")
 			return nil, nil, nil, nil, "", ""
 		}
 	} else {
@@ -523,7 +523,7 @@ func ParseCompareInfo(c *context.Context) (*db.User, *db.Repository, *git.Reposi
 
 	headBranches, err := headGitRepo.Branches()
 	if err != nil {
-		c.ServerError("get branches", err)
+		c.Error(err, "get branches")
 		return nil, nil, nil, nil, "", ""
 	}
 	c.Data["HeadBranches"] = headBranches
@@ -535,7 +535,7 @@ func ParseCompareInfo(c *context.Context) (*db.User, *db.Repository, *git.Reposi
 			c.Data["IsNoMergeBase"] = true
 			c.Success(COMPARE_PULL)
 		} else {
-			c.ServerError("get pull request meta", err)
+			c.Error(err, "get pull request meta")
 		}
 		return nil, nil, nil, nil, "", ""
 	}
@@ -563,7 +563,7 @@ func PrepareCompareDiff(
 
 	headCommitID, err := headGitRepo.BranchCommitID(headBranch)
 	if err != nil {
-		c.ServerError("get head branch commit ID", err)
+		c.Error(err, "get head branch commit ID")
 		return false
 	}
 	c.Data["AfterCommitID"] = headCommitID
@@ -578,7 +578,7 @@ func PrepareCompareDiff(
 		git.DiffOptions{Base: meta.MergeBase},
 	)
 	if err != nil {
-		c.ServerError("get repository diff", err)
+		c.Error(err, "get repository diff")
 		return false
 	}
 	c.Data["Diff"] = diff
@@ -586,7 +586,7 @@ func PrepareCompareDiff(
 
 	headCommit, err := headGitRepo.CatFileCommit(headCommitID)
 	if err != nil {
-		c.ServerError("get head commit", err)
+		c.Error(err, "get head commit")
 		return false
 	}
 
@@ -619,7 +619,7 @@ func CompareAndPullRequest(c *context.Context) {
 	pr, err := db.GetUnmergedPullRequest(headRepo.ID, c.Repo.Repository.ID, headBranch, baseBranch)
 	if err != nil {
 		if !db.IsErrPullRequestNotExist(err) {
-			c.ServerError("GetUnmergedPullRequest", err)
+			c.Error(err, "get unmerged pull request")
 			return
 		}
 	} else {
@@ -701,7 +701,7 @@ func CompareAndPullRequestPost(c *context.Context, f form.NewIssue) {
 
 	patch, err := headGitRepo.DiffBinary(meta.MergeBase, headBranch)
 	if err != nil {
-		c.ServerError("get patch", err)
+		c.Error(err, "get patch")
 		return
 	}
 
@@ -730,10 +730,10 @@ func CompareAndPullRequestPost(c *context.Context, f form.NewIssue) {
 	// FIXME: check error in the case two people send pull request at almost same time, give nice error prompt
 	// instead of 500.
 	if err := db.NewPullRequest(repo, pullIssue, labelIDs, attachments, pullRequest, patch); err != nil {
-		c.ServerError("NewPullRequest", err)
+		c.Error(err, "new pull request")
 		return
 	} else if err := pullRequest.PushToBaseRepo(); err != nil {
-		c.ServerError("PushToBaseRepo", err)
+		c.Error(err, "push to base repository")
 		return
 	}
 
@@ -744,13 +744,13 @@ func CompareAndPullRequestPost(c *context.Context, f form.NewIssue) {
 func parseOwnerAndRepo(c *context.Context) (*db.User, *db.Repository) {
 	owner, err := db.GetUserByName(c.Params(":username"))
 	if err != nil {
-		c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
+		c.NotFoundOrError(err, "get user by name")
 		return nil, nil
 	}
 
 	repo, err := db.GetRepositoryByName(owner.ID, c.Params(":reponame"))
 	if err != nil {
-		c.NotFoundOrServerError("GetRepositoryByName", errors.IsRepoNotExist, err)
+		c.NotFoundOrError(err, "get repository by name")
 		return nil, nil
 	}
 
@@ -762,7 +762,7 @@ func TriggerTask(c *context.Context) {
 	branch := c.Query("branch")
 	secret := c.Query("secret")
 	if len(branch) == 0 || len(secret) == 0 || pusherID <= 0 {
-		c.Error(404)
+		c.NotFound()
 		log.Trace("TriggerTask: branch or secret is empty, or pusher ID is not valid")
 		return
 	}
@@ -771,14 +771,14 @@ func TriggerTask(c *context.Context) {
 		return
 	}
 	if secret != tool.MD5(owner.Salt) {
-		c.Error(404)
+		c.NotFound()
 		log.Trace("TriggerTask [%s/%s]: invalid secret", owner.Name, repo.Name)
 		return
 	}
 
 	pusher, err := db.GetUserByID(pusherID)
 	if err != nil {
-		c.NotFoundOrServerError("GetUserByID", errors.IsUserNotExist, err)
+		c.NotFoundOrError(err, "get user by ID")
 		return
 	}
 

+ 21 - 29
internal/route/repo/release.go

@@ -53,13 +53,13 @@ func Releases(c *context.Context) {
 
 	tagsPage, err := gitutil.Module.ListTagsAfter(c.Repo.GitRepo.Path(), c.Query("after"), 10)
 	if err != nil {
-		c.ServerError("get tags", err)
+		c.Error(err, "get tags")
 		return
 	}
 
 	releases, err := db.GetPublishedReleasesByRepoID(c.Repo.Repository.ID, tagsPage.Tags...)
 	if err != nil {
-		c.Handle(500, "GetPublishedReleasesByRepoID", err)
+		c.Error(err, "get published releases by repository ID")
 		return
 	}
 
@@ -75,12 +75,12 @@ func Releases(c *context.Context) {
 			releases[j] = nil // Mark as used.
 
 			if err = r.LoadAttributes(); err != nil {
-				c.Handle(500, "LoadAttributes", err)
+				c.Error(err, "load attributes")
 				return
 			}
 
 			if err := calReleaseNumCommitsBehind(c.Repo, r, countCache); err != nil {
-				c.Handle(500, "calReleaseNumCommitsBehind", err)
+				c.Error(err, "calculate number of commits after release")
 				return
 			}
 
@@ -93,7 +93,7 @@ func Releases(c *context.Context) {
 		if results[i] == nil {
 			commit, err := c.Repo.GitRepo.TagCommit(rawTag)
 			if err != nil {
-				c.Handle(500, "get tag commit", err)
+				c.Error(err, "get tag commit")
 				return
 			}
 
@@ -105,7 +105,7 @@ func Releases(c *context.Context) {
 
 			results[i].NumCommits, err = commit.CommitsCount()
 			if err != nil {
-				c.ServerError("count commits", err)
+				c.Error(err, "count commits")
 				return
 			}
 			results[i].NumCommitsBehind = c.Repo.CommitsCount - results[i].NumCommits
@@ -118,18 +118,18 @@ func Releases(c *context.Context) {
 	if tagsPage.HasLatest {
 		drafts, err = db.GetDraftReleasesByRepoID(c.Repo.Repository.ID)
 		if err != nil {
-			c.Handle(500, "GetDraftReleasesByRepoID", err)
+			c.Error(err, "get draft releases by repository ID")
 			return
 		}
 
 		for _, r := range drafts {
 			if err = r.LoadAttributes(); err != nil {
-				c.Handle(500, "LoadAttributes", err)
+				c.Error(err, "load attributes")
 				return
 			}
 
 			if err := calReleaseNumCommitsBehind(c.Repo, r, countCache); err != nil {
-				c.Handle(500, "calReleaseNumCommitsBehind", err)
+				c.Error(err, "calculate number of commits after release")
 				return
 			}
 
@@ -148,7 +148,7 @@ func Releases(c *context.Context) {
 	if len(results) > 0 {
 		c.Data["NextAfter"] = results[len(results)-1].TagName
 	}
-	c.HTML(200, RELEASES)
+	c.Success(RELEASES)
 }
 
 func renderReleaseAttachmentSettings(c *context.Context) {
@@ -164,7 +164,7 @@ func NewRelease(c *context.Context) {
 	c.Data["PageIsReleaseList"] = true
 	c.Data["tag_target"] = c.Repo.Repository.DefaultBranch
 	renderReleaseAttachmentSettings(c)
-	c.HTML(200, RELEASE_NEW)
+	c.Success(RELEASE_NEW)
 }
 
 func NewReleasePost(c *context.Context, f form.NewRelease) {
@@ -173,7 +173,7 @@ func NewReleasePost(c *context.Context, f form.NewRelease) {
 	renderReleaseAttachmentSettings(c)
 
 	if c.HasError() {
-		c.HTML(200, RELEASE_NEW)
+		c.Success(RELEASE_NEW)
 		return
 	}
 
@@ -194,13 +194,13 @@ func NewReleasePost(c *context.Context, f form.NewRelease) {
 
 	commit, err := c.Repo.GitRepo.BranchCommit(f.Target)
 	if err != nil {
-		c.ServerError("get branch commit", err)
+		c.Error(err, "get branch commit")
 		return
 	}
 
 	commitsCount, err := commit.CommitsCount()
 	if err != nil {
-		c.ServerError("count commits", err)
+		c.Error(err, "count commits")
 		return
 	}
 
@@ -230,7 +230,7 @@ func NewReleasePost(c *context.Context, f form.NewRelease) {
 		case db.IsErrInvalidTagName(err):
 			c.RenderWithErr(c.Tr("repo.release.tag_name_invalid"), RELEASE_NEW, &f)
 		default:
-			c.Handle(500, "NewRelease", err)
+			c.Error(err, "new release")
 		}
 		return
 	}
@@ -248,11 +248,7 @@ func EditRelease(c *context.Context) {
 	tagName := c.Params("*")
 	rel, err := db.GetRelease(c.Repo.Repository.ID, tagName)
 	if err != nil {
-		if db.IsErrReleaseNotExist(err) {
-			c.Handle(404, "GetRelease", err)
-		} else {
-			c.Handle(500, "GetRelease", err)
-		}
+		c.NotFoundOrError(err, "get release")
 		return
 	}
 	c.Data["ID"] = rel.ID
@@ -264,7 +260,7 @@ func EditRelease(c *context.Context) {
 	c.Data["prerelease"] = rel.IsPrerelease
 	c.Data["IsDraft"] = rel.IsDraft
 
-	c.HTML(200, RELEASE_NEW)
+	c.Success(RELEASE_NEW)
 }
 
 func EditReleasePost(c *context.Context, f form.EditRelease) {
@@ -276,11 +272,7 @@ func EditReleasePost(c *context.Context, f form.EditRelease) {
 	tagName := c.Params("*")
 	rel, err := db.GetRelease(c.Repo.Repository.ID, tagName)
 	if err != nil {
-		if db.IsErrReleaseNotExist(err) {
-			c.Handle(404, "GetRelease", err)
-		} else {
-			c.Handle(500, "GetRelease", err)
-		}
+		c.NotFoundOrError(err, "get release")
 		return
 	}
 	c.Data["tag_name"] = rel.TagName
@@ -292,7 +284,7 @@ func EditReleasePost(c *context.Context, f form.EditRelease) {
 	c.Data["IsDraft"] = rel.IsDraft
 
 	if c.HasError() {
-		c.HTML(200, RELEASE_NEW)
+		c.Success(RELEASE_NEW)
 		return
 	}
 
@@ -307,7 +299,7 @@ func EditReleasePost(c *context.Context, f form.EditRelease) {
 	rel.IsDraft = len(f.Draft) > 0
 	rel.IsPrerelease = f.Prerelease
 	if err = db.UpdateRelease(c.User, c.Repo.GitRepo, rel, isPublish, attachments); err != nil {
-		c.Handle(500, "UpdateRelease", err)
+		c.Error(err, "update release")
 		return
 	}
 	c.Redirect(c.Repo.RepoLink + "/releases")
@@ -328,7 +320,7 @@ func DeleteRelease(c *context.Context) {
 		c.Flash.Success(c.Tr("repo.release.deletion_success"))
 	}
 
-	c.JSON(200, map[string]interface{}{
+	c.JSONSuccess( map[string]interface{}{
 		"redirect": c.Repo.RepoLink + "/releases",
 	})
 }

+ 20 - 21
internal/route/repo/repo.go

@@ -5,7 +5,7 @@
 package repo
 
 import (
-	"fmt"
+	"net/http"
 	"os"
 	"path"
 	"path/filepath"
@@ -19,7 +19,6 @@ import (
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
 	"gogs.io/gogs/internal/form"
 	"gogs.io/gogs/internal/tool"
 )
@@ -31,14 +30,14 @@ const (
 
 func MustBeNotBare(c *context.Context) {
 	if c.Repo.Repository.IsBare {
-		c.Handle(404, "MustBeNotBare", nil)
+		c.NotFound()
 	}
 }
 
 func checkContextUser(c *context.Context, uid int64) *db.User {
 	orgs, err := db.GetOwnedOrgsByUserIDDesc(c.User.ID, "updated_unix")
 	if err != nil {
-		c.Handle(500, "GetOwnedOrgsByUserIDDesc", err)
+		c.Error(err, "get owned organization by user ID")
 		return nil
 	}
 	c.Data["Orgs"] = orgs
@@ -49,18 +48,18 @@ func checkContextUser(c *context.Context, uid int64) *db.User {
 	}
 
 	org, err := db.GetUserByID(uid)
-	if errors.IsUserNotExist(err) {
+	if db.IsErrUserNotExist(err) {
 		return c.User
 	}
 
 	if err != nil {
-		c.Handle(500, "GetUserByID", fmt.Errorf("[%d]: %v", uid, err))
+		c.Error(err, "get user by ID")
 		return nil
 	}
 
 	// Check ownership of organization.
 	if !org.IsOrganization() || !(c.User.IsAdmin || org.IsOwnedBy(c.User.ID)) {
-		c.Error(403)
+		c.Status(http.StatusForbidden)
 		return nil
 	}
 	return org
@@ -84,12 +83,12 @@ func Create(c *context.Context) {
 	}
 	c.Data["ContextUser"] = ctxUser
 
-	c.HTML(200, CREATE)
+	c.Success(CREATE)
 }
 
 func handleCreateError(c *context.Context, owner *db.User, err error, name, tpl string, form interface{}) {
 	switch {
-	case errors.IsReachLimitOfRepo(err):
+	case db.IsErrReachLimitOfRepo(err):
 		c.RenderWithErr(c.Tr("repo.form.reach_limit_of_creation", owner.RepoCreationNum()), tpl, form)
 	case db.IsErrRepoAlreadyExist(err):
 		c.Data["Err_RepoName"] = true
@@ -101,7 +100,7 @@ func handleCreateError(c *context.Context, owner *db.User, err error, name, tpl
 		c.Data["Err_RepoName"] = true
 		c.RenderWithErr(c.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), tpl, form)
 	default:
-		c.Handle(500, name, err)
+		c.Error(err, name)
 	}
 }
 
@@ -119,7 +118,7 @@ func CreatePost(c *context.Context, f form.CreateRepo) {
 	c.Data["ContextUser"] = ctxUser
 
 	if c.HasError() {
-		c.HTML(200, CREATE)
+		c.Success(CREATE)
 		return
 	}
 
@@ -159,7 +158,7 @@ func Migrate(c *context.Context) {
 	}
 	c.Data["ContextUser"] = ctxUser
 
-	c.HTML(200, MIGRATE)
+	c.Success(MIGRATE)
 }
 
 func MigratePost(c *context.Context, f form.MigrateRepo) {
@@ -172,7 +171,7 @@ func MigratePost(c *context.Context, f form.MigrateRepo) {
 	c.Data["ContextUser"] = ctxUser
 
 	if c.HasError() {
-		c.HTML(200, MIGRATE)
+		c.Success(MIGRATE)
 		return
 	}
 
@@ -189,10 +188,10 @@ func MigratePost(c *context.Context, f form.MigrateRepo) {
 			case addrErr.IsInvalidPath:
 				c.RenderWithErr(c.Tr("repo.migrate.invalid_local_path"), MIGRATE, &f)
 			default:
-				c.Handle(500, "Unknown error", err)
+				c.Error(err, "unexpected error")
 			}
 		} else {
-			c.Handle(500, "ParseRemoteAddr", err)
+			c.Error(err, "parse remote address")
 		}
 		return
 	}
@@ -259,7 +258,7 @@ func Action(c *context.Context) {
 	}
 
 	if err != nil {
-		c.ServerError(fmt.Sprintf("Action (%s)", c.Params(":action")), err)
+		c.Errorf(err, "action %q", c.Params(":action"))
 		return
 	}
 
@@ -290,14 +289,14 @@ func Download(c *context.Context) {
 		archiveFormat = git.ArchiveTarGz
 	default:
 		log.Trace("Unknown format: %s", uri)
-		c.Error(404)
+		c.NotFound()
 		return
 	}
 	refName = strings.TrimSuffix(uri, ext)
 
 	if !com.IsDir(archivePath) {
 		if err := os.MkdirAll(archivePath, os.ModePerm); err != nil {
-			c.Handle(500, "Download -> os.MkdirAll(archivePath)", err)
+			c.Error(err, "create archive directory")
 			return
 		}
 	}
@@ -311,13 +310,13 @@ func Download(c *context.Context) {
 	if gitRepo.HasBranch(refName) {
 		commit, err = gitRepo.BranchCommit(refName)
 		if err != nil {
-			c.ServerError("get branch commit", err)
+			c.Error(err, "get branch commit")
 			return
 		}
 	} else if gitRepo.HasTag(refName) {
 		commit, err = gitRepo.TagCommit(refName)
 		if err != nil {
-			c.ServerError("get tag commit", err)
+			c.Error(err, "get tag commit")
 			return
 		}
 	} else if len(refName) >= 7 && len(refName) <= 40 {
@@ -334,7 +333,7 @@ func Download(c *context.Context) {
 	archivePath = path.Join(archivePath, tool.ShortSHA1(commit.ID.String())+ext)
 	if !com.IsFile(archivePath) {
 		if err := commit.CreateArchive(archiveFormat, archivePath); err != nil {
-			c.ServerError("creates archive", err)
+			c.Error(err, "creates archive")
 			return
 		}
 	}

+ 44 - 52
internal/route/repo/setting.go

@@ -7,7 +7,6 @@ package repo
 import (
 	"fmt"
 	"io/ioutil"
-	"os"
 	"strings"
 	"time"
 
@@ -21,6 +20,7 @@ import (
 	"gogs.io/gogs/internal/db/errors"
 	"gogs.io/gogs/internal/email"
 	"gogs.io/gogs/internal/form"
+	"gogs.io/gogs/internal/osutil"
 	"gogs.io/gogs/internal/tool"
 )
 
@@ -72,7 +72,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) {
 				case db.IsErrNamePatternNotAllowed(err):
 					c.RenderWithErr(c.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), SETTINGS_OPTIONS, &f)
 				default:
-					c.ServerError("ChangeRepositoryName", err)
+					c.Error(err, "change repository name")
 				}
 				return
 			}
@@ -94,7 +94,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) {
 		visibilityChanged := repo.IsPrivate != f.Private
 		repo.IsPrivate = f.Private
 		if err := db.UpdateRepository(repo, visibilityChanged); err != nil {
-			c.ServerError("UpdateRepository", err)
+			c.Error(err, "update repository")
 			return
 		}
 		log.Trace("Repository basic settings updated: %s/%s", c.Repo.Owner.Name, repo.Name)
@@ -119,12 +119,12 @@ func SettingsPost(c *context.Context, f form.RepoSetting) {
 			c.Repo.Mirror.Interval = f.Interval
 			c.Repo.Mirror.NextSync = time.Now().Add(time.Duration(f.Interval) * time.Hour)
 			if err := db.UpdateMirror(c.Repo.Mirror); err != nil {
-				c.ServerError("UpdateMirror", err)
+				c.Error(err, "update mirror")
 				return
 			}
 		}
 		if err := c.Repo.Mirror.SaveAddress(f.MirrorAddress); err != nil {
-			c.ServerError("SaveAddress", err)
+			c.Error(err, "save address")
 			return
 		}
 
@@ -157,7 +157,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) {
 		repo.PullsAllowRebase = f.PullsAllowRebase
 
 		if err := db.UpdateRepository(repo, false); err != nil {
-			c.ServerError("UpdateRepository", err)
+			c.Error(err, "update repository")
 			return
 		}
 		log.Trace("Repository advanced settings updated: %s/%s", c.Repo.Owner.Name, repo.Name)
@@ -189,10 +189,10 @@ func SettingsPost(c *context.Context, f form.RepoSetting) {
 		repo.IsMirror = false
 
 		if _, err := db.CleanUpMigrateInfo(repo); err != nil {
-			c.ServerError("CleanUpMigrateInfo", err)
+			c.Error(err, "clean up migrate info")
 			return
 		} else if err = db.DeleteMirrorByRepoID(c.Repo.Repository.ID); err != nil {
-			c.ServerError("DeleteMirrorByRepoID", err)
+			c.Error(err, "delete mirror by repository ID")
 			return
 		}
 		log.Trace("Repository converted from mirror to regular: %s/%s", c.Repo.Owner.Name, repo.Name)
@@ -219,7 +219,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) {
 		newOwner := c.Query("new_owner_name")
 		isExist, err := db.IsUserExist(0, newOwner)
 		if err != nil {
-			c.ServerError("IsUserExist", err)
+			c.Error(err, "check if user exists")
 			return
 		} else if !isExist {
 			c.RenderWithErr(c.Tr("form.enterred_invalid_owner_name"), SETTINGS_OPTIONS, nil)
@@ -230,7 +230,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) {
 			if db.IsErrRepoAlreadyExist(err) {
 				c.RenderWithErr(c.Tr("repo.settings.new_owner_has_same_repo"), SETTINGS_OPTIONS, nil)
 			} else {
-				c.ServerError("TransferOwnership", err)
+				c.Error(err, "transfer ownership")
 			}
 			return
 		}
@@ -256,7 +256,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) {
 		}
 
 		if err := db.DeleteRepository(c.Repo.Owner.ID, repo.ID); err != nil {
-			c.ServerError("DeleteRepository", err)
+			c.Error(err, "delete repository")
 			return
 		}
 		log.Trace("Repository deleted: %s/%s", c.Repo.Owner.Name, repo.Name)
@@ -286,7 +286,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) {
 
 		repo.EnableWiki = false
 		if err := db.UpdateRepository(repo, false); err != nil {
-			c.ServerError("UpdateRepository", err)
+			c.Error(err, "update repository")
 			return
 		}
 
@@ -311,14 +311,14 @@ func SettingsAvatarPost(c *context.Context, f form.Avatar) {
 	} else {
 		c.Flash.Success(c.Tr("settings.update_avatar_success"))
 	}
-	c.SubURLRedirect(c.Repo.RepoLink + "/settings")
+	c.RedirectSubpath(c.Repo.RepoLink + "/settings")
 }
 
 func SettingsDeleteAvatar(c *context.Context) {
 	if err := c.Repo.Repository.DeleteAvatar(); err != nil {
 		c.Flash.Error(fmt.Sprintf("Failed to delete avatar: %v", err))
 	}
-	c.SubURLRedirect(c.Repo.RepoLink + "/settings")
+	c.RedirectSubpath(c.Repo.RepoLink + "/settings")
 }
 
 // FIXME: limit upload size
@@ -361,12 +361,12 @@ func SettingsCollaboration(c *context.Context) {
 
 	users, err := c.Repo.Repository.GetCollaborators()
 	if err != nil {
-		c.Handle(500, "GetCollaborators", err)
+		c.Error(err, "get collaborators")
 		return
 	}
 	c.Data["Collaborators"] = users
 
-	c.HTML(200, SETTINGS_COLLABORATION)
+	c.Success(SETTINGS_COLLABORATION)
 }
 
 func SettingsCollaborationPost(c *context.Context) {
@@ -378,11 +378,11 @@ func SettingsCollaborationPost(c *context.Context) {
 
 	u, err := db.GetUserByName(name)
 	if err != nil {
-		if errors.IsUserNotExist(err) {
+		if db.IsErrUserNotExist(err) {
 			c.Flash.Error(c.Tr("form.user_not_exist"))
 			c.Redirect(conf.Server.Subpath + c.Req.URL.Path)
 		} else {
-			c.Handle(500, "GetUserByName", err)
+			c.Error(err, "get user by name")
 		}
 		return
 	}
@@ -395,7 +395,7 @@ func SettingsCollaborationPost(c *context.Context) {
 	}
 
 	if err = c.Repo.Repository.AddCollaborator(u); err != nil {
-		c.Handle(500, "AddCollaborator", err)
+		c.Error(err, "add collaborator")
 		return
 	}
 
@@ -425,7 +425,7 @@ func DeleteCollaboration(c *context.Context) {
 		c.Flash.Success(c.Tr("repo.settings.remove_collaborator_success"))
 	}
 
-	c.JSON(200, map[string]interface{}{
+	c.JSONSuccess( map[string]interface{}{
 		"redirect": c.Repo.RepoLink + "/settings/collaboration",
 	})
 }
@@ -436,13 +436,13 @@ func SettingsBranches(c *context.Context) {
 
 	if c.Repo.Repository.IsBare {
 		c.Flash.Info(c.Tr("repo.settings.branches_bare"), true)
-		c.HTML(200, SETTINGS_BRANCHES)
+		c.Success(SETTINGS_BRANCHES)
 		return
 	}
 
 	protectBranches, err := db.GetProtectBranchesByRepoID(c.Repo.Repository.ID)
 	if err != nil {
-		c.Handle(500, "GetProtectBranchesByRepoID", err)
+		c.Error(err, "get protect branch by repository ID")
 		return
 	}
 
@@ -455,7 +455,7 @@ func SettingsBranches(c *context.Context) {
 	}
 	c.Data["ProtectBranches"] = branches
 
-	c.HTML(200, SETTINGS_BRANCHES)
+	c.Success(SETTINGS_BRANCHES)
 }
 
 func UpdateDefaultBranch(c *context.Context) {
@@ -473,7 +473,7 @@ func UpdateDefaultBranch(c *context.Context) {
 	}
 
 	if err := db.UpdateRepository(c.Repo.Repository, false); err != nil {
-		c.Handle(500, "UpdateRepository", err)
+		c.Error(err, "update repository")
 		return
 	}
 
@@ -493,8 +493,8 @@ func SettingsProtectedBranch(c *context.Context) {
 
 	protectBranch, err := db.GetProtectBranchOfRepoByName(c.Repo.Repository.ID, branch)
 	if err != nil {
-		if !errors.IsErrBranchNotExist(err) {
-			c.Handle(500, "GetProtectBranchOfRepoByName", err)
+		if !db.IsErrBranchNotExist(err) {
+			c.Error(err, "get protect branch of repository by name")
 			return
 		}
 
@@ -507,7 +507,7 @@ func SettingsProtectedBranch(c *context.Context) {
 	if c.Repo.Owner.IsOrganization() {
 		users, err := c.Repo.Repository.GetWriters()
 		if err != nil {
-			c.Handle(500, "Repo.Repository.GetPushers", err)
+			c.Error(err, "get writers")
 			return
 		}
 		c.Data["Users"] = users
@@ -515,7 +515,7 @@ func SettingsProtectedBranch(c *context.Context) {
 
 		teams, err := c.Repo.Owner.TeamsHaveAccessToRepo(c.Repo.Repository.ID, db.ACCESS_MODE_WRITE)
 		if err != nil {
-			c.Handle(500, "Repo.Owner.TeamsHaveAccessToRepo", err)
+			c.Error(err, "get teams have access to the repository")
 			return
 		}
 		c.Data["Teams"] = teams
@@ -523,7 +523,7 @@ func SettingsProtectedBranch(c *context.Context) {
 	}
 
 	c.Data["Branch"] = protectBranch
-	c.HTML(200, SETTINGS_PROTECTED_BRANCH)
+	c.Success(SETTINGS_PROTECTED_BRANCH)
 }
 
 func SettingsProtectedBranchPost(c *context.Context, f form.ProtectBranch) {
@@ -535,8 +535,8 @@ func SettingsProtectedBranchPost(c *context.Context, f form.ProtectBranch) {
 
 	protectBranch, err := db.GetProtectBranchOfRepoByName(c.Repo.Repository.ID, branch)
 	if err != nil {
-		if !errors.IsErrBranchNotExist(err) {
-			c.Handle(500, "GetProtectBranchOfRepoByName", err)
+		if !db.IsErrBranchNotExist(err) {
+			c.Error(err, "get protect branch of repository by name")
 			return
 		}
 
@@ -556,7 +556,7 @@ func SettingsProtectedBranchPost(c *context.Context, f form.ProtectBranch) {
 		err = db.UpdateProtectBranch(protectBranch)
 	}
 	if err != nil {
-		c.Handle(500, "UpdateOrgProtectBranch/UpdateProtectBranch", err)
+		c.Error(err, "update protect branch")
 		return
 	}
 
@@ -570,12 +570,12 @@ func SettingsGitHooks(c *context.Context) {
 
 	hooks, err := c.Repo.GitRepo.Hooks("custom_hooks")
 	if err != nil {
-		c.Handle(500, "Hooks", err)
+		c.Error(err, "get hooks")
 		return
 	}
 	c.Data["Hooks"] = hooks
 
-	c.HTML(200, SETTINGS_GITHOOKS)
+	c.Success(SETTINGS_GITHOOKS)
 }
 
 func SettingsGitHooksEdit(c *context.Context) {
@@ -586,30 +586,22 @@ func SettingsGitHooksEdit(c *context.Context) {
 	name := c.Params(":name")
 	hook, err := c.Repo.GitRepo.Hook("custom_hooks", git.HookName(name))
 	if err != nil {
-		if err == os.ErrNotExist {
-			c.Handle(404, "GetHook", err)
-		} else {
-			c.Handle(500, "GetHook", err)
-		}
+		c.NotFoundOrError(osutil.NewError(err), "get hook")
 		return
 	}
 	c.Data["Hook"] = hook
-	c.HTML(200, SETTINGS_GITHOOK_EDIT)
+	c.Success(SETTINGS_GITHOOK_EDIT)
 }
 
 func SettingsGitHooksEditPost(c *context.Context) {
 	name := c.Params(":name")
 	hook, err := c.Repo.GitRepo.Hook("custom_hooks", git.HookName(name))
 	if err != nil {
-		if err == os.ErrNotExist {
-			c.Handle(404, "GetHook", err)
-		} else {
-			c.Handle(500, "GetHook", err)
-		}
+		c.NotFoundOrError(osutil.NewError(err), "get hook")
 		return
 	}
 	if err = hook.Update(c.Query("content")); err != nil {
-		c.Handle(500, "hook.Update", err)
+		c.Error(err, "update hook")
 		return
 	}
 	c.Redirect(c.Data["Link"].(string))
@@ -621,12 +613,12 @@ func SettingsDeployKeys(c *context.Context) {
 
 	keys, err := db.ListDeployKeys(c.Repo.Repository.ID)
 	if err != nil {
-		c.Handle(500, "ListDeployKeys", err)
+		c.Error(err, "list deploy keys")
 		return
 	}
 	c.Data["Deploykeys"] = keys
 
-	c.HTML(200, SETTINGS_DEPLOY_KEYS)
+	c.Success(SETTINGS_DEPLOY_KEYS)
 }
 
 func SettingsDeployKeysPost(c *context.Context, f form.AddSSHKey) {
@@ -635,13 +627,13 @@ func SettingsDeployKeysPost(c *context.Context, f form.AddSSHKey) {
 
 	keys, err := db.ListDeployKeys(c.Repo.Repository.ID)
 	if err != nil {
-		c.Handle(500, "ListDeployKeys", err)
+		c.Error(err, "list deploy keys")
 		return
 	}
 	c.Data["Deploykeys"] = keys
 
 	if c.HasError() {
-		c.HTML(200, SETTINGS_DEPLOY_KEYS)
+		c.Success(SETTINGS_DEPLOY_KEYS)
 		return
 	}
 
@@ -669,7 +661,7 @@ func SettingsDeployKeysPost(c *context.Context, f form.AddSSHKey) {
 			c.Data["Err_Title"] = true
 			c.RenderWithErr(c.Tr("repo.settings.key_name_used"), SETTINGS_DEPLOY_KEYS, &f)
 		default:
-			c.Handle(500, "AddDeployKey", err)
+			c.Error(err, "add deploy key")
 		}
 		return
 	}
@@ -686,7 +678,7 @@ func DeleteDeployKey(c *context.Context) {
 		c.Flash.Success(c.Tr("repo.settings.deploy_key_deletion_success"))
 	}
 
-	c.JSON(200, map[string]interface{}{
+	c.JSONSuccess( map[string]interface{}{
 		"redirect": c.Repo.RepoLink + "/settings/keys",
 	})
 }

+ 15 - 15
internal/route/repo/view.go

@@ -37,13 +37,13 @@ const (
 func renderDirectory(c *context.Context, treeLink string) {
 	tree, err := c.Repo.Commit.Subtree(c.Repo.TreePath)
 	if err != nil {
-		c.NotFoundOrServerError("get subtree", gitutil.IsErrRevisionNotExist, err)
+		c.NotFoundOrError(gitutil.NewError(err), "get subtree")
 		return
 	}
 
 	entries, err := tree.Entries()
 	if err != nil {
-		c.ServerError("list entries", err)
+		c.Error(err, "list entries")
 		return
 	}
 	entries.Sort()
@@ -54,7 +54,7 @@ func renderDirectory(c *context.Context, treeLink string) {
 		Timeout:        5 * time.Minute,
 	})
 	if err != nil {
-		c.ServerError("get commits info", err)
+		c.Error(err, "get commits info")
 		return
 	}
 
@@ -76,7 +76,7 @@ func renderDirectory(c *context.Context, treeLink string) {
 
 		p, err := readmeFile.Bytes()
 		if err != nil {
-			c.ServerError("readmeFile.Data", err)
+			c.Error(err, "read file")
 			return
 		}
 
@@ -107,7 +107,7 @@ func renderDirectory(c *context.Context, treeLink string) {
 	if len(c.Repo.TreePath) > 0 {
 		latestCommit, err = c.Repo.Commit.CommitByPath(git.CommitByRevisionOptions{Path: c.Repo.TreePath})
 		if err != nil {
-			c.ServerError("get commit by path", err)
+			c.Error(err, "get commit by path")
 			return
 		}
 	}
@@ -126,7 +126,7 @@ func renderFile(c *context.Context, entry *git.TreeEntry, treeLink, rawLink stri
 	blob := entry.Blob()
 	p, err := blob.Bytes()
 	if err != nil {
-		c.Handle(500, "Data", err)
+		c.Error(err, "read blob")
 		return
 	}
 
@@ -232,7 +232,7 @@ func Home(c *context.Context) {
 	c.Data["PageIsViewFiles"] = true
 
 	if c.Repo.Repository.IsBare {
-		c.HTML(200, BARE)
+		c.Success(BARE)
 		return
 	}
 
@@ -260,7 +260,7 @@ func Home(c *context.Context) {
 		var err error
 		c.Repo.CommitsCount, err = c.Repo.Commit.CommitsCount()
 		if err != nil {
-			c.Handle(500, "CommitsCount", err)
+			c.Error(err, "count commits")
 			return
 		}
 		c.Data["CommitsCount"] = c.Repo.CommitsCount
@@ -270,7 +270,7 @@ func Home(c *context.Context) {
 	// Get current entry user currently looking at.
 	entry, err := c.Repo.Commit.TreeEntry(c.Repo.TreePath)
 	if err != nil {
-		c.NotFoundOrServerError("get tree entry", gitutil.IsErrRevisionNotExist, err)
+		c.NotFoundOrError(gitutil.NewError(err), "get tree entry")
 		return
 	}
 
@@ -306,7 +306,7 @@ func Home(c *context.Context) {
 	c.Data["TreeLink"] = treeLink
 	c.Data["TreeNames"] = treeNames
 	c.Data["BranchLink"] = branchLink
-	c.HTML(200, HOME)
+	c.Success(HOME)
 }
 
 func RenderUserCards(c *context.Context, total int, getter func(page int) ([]*db.User, error), tpl string) {
@@ -319,12 +319,12 @@ func RenderUserCards(c *context.Context, total int, getter func(page int) ([]*db
 
 	items, err := getter(pager.Current())
 	if err != nil {
-		c.Handle(500, "getter", err)
+		c.Error(err, "getter")
 		return
 	}
 	c.Data["Cards"] = items
 
-	c.HTML(200, tpl)
+	c.Success(tpl)
 }
 
 func Watchers(c *context.Context) {
@@ -346,17 +346,17 @@ func Forks(c *context.Context) {
 
 	forks, err := c.Repo.Repository.GetForks()
 	if err != nil {
-		c.Handle(500, "GetForks", err)
+		c.Error(err, "get forks")
 		return
 	}
 
 	for _, fork := range forks {
 		if err = fork.GetOwner(); err != nil {
-			c.Handle(500, "GetOwner", err)
+			c.Error(err, "get owner")
 			return
 		}
 	}
 	c.Data["Forks"] = forks
 
-	c.HTML(200, FORKS)
+	c.Success(FORKS)
 }

+ 62 - 58
internal/route/repo/webhook.go

@@ -6,6 +6,7 @@ package repo
 
 import (
 	"fmt"
+	"net/http"
 	"strings"
 
 	jsoniter "github.com/json-iterator/go"
@@ -36,12 +37,12 @@ func Webhooks(c *context.Context) {
 
 	ws, err := db.GetWebhooksByRepoID(c.Repo.Repository.ID)
 	if err != nil {
-		c.Handle(500, "GetWebhooksByRepoID", err)
+		c.Error(err, "get webhooks by repository ID")
 		return
 	}
 	c.Data["Webhooks"] = ws
 
-	c.HTML(200, WEBHOOKS)
+	c.Success(WEBHOOKS)
 }
 
 type OrgRepoCtx struct {
@@ -77,7 +78,7 @@ func getOrgRepoCtx(c *context.Context) (*OrgRepoCtx, error) {
 func checkHookType(c *context.Context) string {
 	hookType := strings.ToLower(c.Params(":type"))
 	if !com.IsSliceContainsStr(conf.Webhook.Types, hookType) {
-		c.Handle(404, "checkHookType", nil)
+		c.NotFound()
 		return ""
 	}
 	return hookType
@@ -91,7 +92,7 @@ func WebhooksNew(c *context.Context) {
 
 	orCtx, err := getOrgRepoCtx(c)
 	if err != nil {
-		c.Handle(500, "getOrgRepoCtx", err)
+		c.Error(err, "get organization repository context")
 		return
 	}
 
@@ -101,7 +102,7 @@ func WebhooksNew(c *context.Context) {
 	}
 	c.Data["BaseLink"] = orCtx.Link
 
-	c.HTML(200, orCtx.NewTemplate)
+	c.Success(orCtx.NewTemplate)
 }
 
 func ParseHookEvent(f form.Webhook) *db.HookEvent {
@@ -131,13 +132,13 @@ func WebHooksNewPost(c *context.Context, f form.NewWebhook) {
 
 	orCtx, err := getOrgRepoCtx(c)
 	if err != nil {
-		c.Handle(500, "getOrgRepoCtx", err)
+		c.Error(err, "get organization repository context")
 		return
 	}
 	c.Data["BaseLink"] = orCtx.Link
 
 	if c.HasError() {
-		c.HTML(200, orCtx.NewTemplate)
+		c.Success(orCtx.NewTemplate)
 		return
 	}
 
@@ -157,10 +158,10 @@ func WebHooksNewPost(c *context.Context, f form.NewWebhook) {
 		OrgID:        orCtx.OrgID,
 	}
 	if err := w.UpdateEvent(); err != nil {
-		c.Handle(500, "UpdateEvent", err)
+		c.Error(err, "update event")
 		return
 	} else if err := db.CreateWebhook(w); err != nil {
-		c.Handle(500, "CreateWebhook", err)
+		c.Error(err, "create webhook")
 		return
 	}
 
@@ -176,12 +177,12 @@ func SlackHooksNewPost(c *context.Context, f form.NewSlackHook) {
 
 	orCtx, err := getOrgRepoCtx(c)
 	if err != nil {
-		c.Handle(500, "getOrgRepoCtx", err)
+		c.Error(err, "get organization repository context")
 		return
 	}
 
 	if c.HasError() {
-		c.HTML(200, orCtx.NewTemplate)
+		c.Success(orCtx.NewTemplate)
 		return
 	}
 
@@ -192,7 +193,7 @@ func SlackHooksNewPost(c *context.Context, f form.NewSlackHook) {
 		Color:    f.Color,
 	})
 	if err != nil {
-		c.Handle(500, "Marshal", err)
+		c.Error(err, "marshal JSON")
 		return
 	}
 
@@ -207,10 +208,10 @@ func SlackHooksNewPost(c *context.Context, f form.NewSlackHook) {
 		OrgID:        orCtx.OrgID,
 	}
 	if err := w.UpdateEvent(); err != nil {
-		c.Handle(500, "UpdateEvent", err)
+		c.Error(err, "update event")
 		return
 	} else if err := db.CreateWebhook(w); err != nil {
-		c.Handle(500, "CreateWebhook", err)
+		c.Error(err, "create webhook")
 		return
 	}
 
@@ -227,12 +228,12 @@ func DiscordHooksNewPost(c *context.Context, f form.NewDiscordHook) {
 
 	orCtx, err := getOrgRepoCtx(c)
 	if err != nil {
-		c.Handle(500, "getOrgRepoCtx", err)
+		c.Error(err, "get organization repository context")
 		return
 	}
 
 	if c.HasError() {
-		c.HTML(200, orCtx.NewTemplate)
+		c.Success(orCtx.NewTemplate)
 		return
 	}
 
@@ -242,7 +243,7 @@ func DiscordHooksNewPost(c *context.Context, f form.NewDiscordHook) {
 		Color:    f.Color,
 	})
 	if err != nil {
-		c.Handle(500, "Marshal", err)
+		c.Error(err, "marshal JSON")
 		return
 	}
 
@@ -257,10 +258,10 @@ func DiscordHooksNewPost(c *context.Context, f form.NewDiscordHook) {
 		OrgID:        orCtx.OrgID,
 	}
 	if err := w.UpdateEvent(); err != nil {
-		c.Handle(500, "UpdateEvent", err)
+		c.Error(err, "update event")
 		return
 	} else if err := db.CreateWebhook(w); err != nil {
-		c.Handle(500, "CreateWebhook", err)
+		c.Error(err, "create webhook")
 		return
 	}
 
@@ -276,12 +277,12 @@ func DingtalkHooksNewPost(c *context.Context, f form.NewDingtalkHook) {
 
 	orCtx, err := getOrgRepoCtx(c)
 	if err != nil {
-		c.Handle(500, "getOrgRepoCtx", err)
+		c.Error(err, "get organization repository context")
 		return
 	}
 
 	if c.HasError() {
-		c.HTML(200, orCtx.NewTemplate)
+		c.Success(orCtx.NewTemplate)
 		return
 	}
 
@@ -295,10 +296,10 @@ func DingtalkHooksNewPost(c *context.Context, f form.NewDingtalkHook) {
 		OrgID:        orCtx.OrgID,
 	}
 	if err := w.UpdateEvent(); err != nil {
-		c.Handle(500, "UpdateEvent", err)
+		c.Error(err, "update event")
 		return
 	} else if err := db.CreateWebhook(w); err != nil {
-		c.Handle(500, "CreateWebhook", err)
+		c.Error(err, "create webhook")
 		return
 	}
 
@@ -311,7 +312,7 @@ func checkWebhook(c *context.Context) (*OrgRepoCtx, *db.Webhook) {
 
 	orCtx, err := getOrgRepoCtx(c)
 	if err != nil {
-		c.Handle(500, "getOrgRepoCtx", err)
+		c.Error(err, "get organization repository context")
 		return nil, nil
 	}
 	c.Data["BaseLink"] = orCtx.Link
@@ -323,7 +324,7 @@ func checkWebhook(c *context.Context) (*OrgRepoCtx, *db.Webhook) {
 		w, err = db.GetWebhookByOrgID(c.Org.Organization.ID, c.ParamsInt64(":id"))
 	}
 	if err != nil {
-		c.NotFoundOrServerError("GetWebhookOfRepoByID/GetWebhookByOrgID", errors.IsWebhookNotExist, err)
+		c.NotFoundOrError(err, "get webhook")
 		return nil, nil
 	}
 
@@ -342,7 +343,8 @@ func checkWebhook(c *context.Context) (*OrgRepoCtx, *db.Webhook) {
 
 	c.Data["History"], err = w.History(1)
 	if err != nil {
-		c.Handle(500, "History", err)
+		c.Error(err, "get history")
+		return nil, nil
 	}
 	return orCtx, w
 }
@@ -358,7 +360,7 @@ func WebHooksEdit(c *context.Context) {
 	}
 	c.Data["Webhook"] = w
 
-	c.HTML(200, orCtx.NewTemplate)
+	c.Success(orCtx.NewTemplate)
 }
 
 func WebHooksEditPost(c *context.Context, f form.NewWebhook) {
@@ -373,7 +375,7 @@ func WebHooksEditPost(c *context.Context, f form.NewWebhook) {
 	c.Data["Webhook"] = w
 
 	if c.HasError() {
-		c.HTML(200, orCtx.NewTemplate)
+		c.Success(orCtx.NewTemplate)
 		return
 	}
 
@@ -388,10 +390,10 @@ func WebHooksEditPost(c *context.Context, f form.NewWebhook) {
 	w.HookEvent = ParseHookEvent(f.Webhook)
 	w.IsActive = f.Active
 	if err := w.UpdateEvent(); err != nil {
-		c.Handle(500, "UpdateEvent", err)
+		c.Error(err, "update event")
 		return
 	} else if err := db.UpdateWebhook(w); err != nil {
-		c.Handle(500, "WebHooksEditPost", err)
+		c.Error(err, "update webhook")
 		return
 	}
 
@@ -411,7 +413,7 @@ func SlackHooksEditPost(c *context.Context, f form.NewSlackHook) {
 	c.Data["Webhook"] = w
 
 	if c.HasError() {
-		c.HTML(200, orCtx.NewTemplate)
+		c.Success(orCtx.NewTemplate)
 		return
 	}
 
@@ -422,7 +424,7 @@ func SlackHooksEditPost(c *context.Context, f form.NewSlackHook) {
 		Color:    f.Color,
 	})
 	if err != nil {
-		c.Handle(500, "Marshal", err)
+		c.Error(err, "marshal JSON")
 		return
 	}
 
@@ -431,10 +433,10 @@ func SlackHooksEditPost(c *context.Context, f form.NewSlackHook) {
 	w.HookEvent = ParseHookEvent(f.Webhook)
 	w.IsActive = f.Active
 	if err := w.UpdateEvent(); err != nil {
-		c.Handle(500, "UpdateEvent", err)
+		c.Error(err, "update event")
 		return
 	} else if err := db.UpdateWebhook(w); err != nil {
-		c.Handle(500, "UpdateWebhook", err)
+		c.Error(err, "update webhook")
 		return
 	}
 
@@ -455,7 +457,7 @@ func DiscordHooksEditPost(c *context.Context, f form.NewDiscordHook) {
 	c.Data["Webhook"] = w
 
 	if c.HasError() {
-		c.HTML(200, orCtx.NewTemplate)
+		c.Success(orCtx.NewTemplate)
 		return
 	}
 
@@ -465,7 +467,7 @@ func DiscordHooksEditPost(c *context.Context, f form.NewDiscordHook) {
 		Color:    f.Color,
 	})
 	if err != nil {
-		c.Handle(500, "Marshal", err)
+		c.Error(err, "marshal JSON")
 		return
 	}
 
@@ -474,10 +476,10 @@ func DiscordHooksEditPost(c *context.Context, f form.NewDiscordHook) {
 	w.HookEvent = ParseHookEvent(f.Webhook)
 	w.IsActive = f.Active
 	if err := w.UpdateEvent(); err != nil {
-		c.Handle(500, "UpdateEvent", err)
+		c.Error(err, "update event")
 		return
 	} else if err := db.UpdateWebhook(w); err != nil {
-		c.Handle(500, "UpdateWebhook", err)
+		c.Error(err, "update webhook")
 		return
 	}
 
@@ -497,7 +499,7 @@ func DingtalkHooksEditPost(c *context.Context, f form.NewDingtalkHook) {
 	c.Data["Webhook"] = w
 
 	if c.HasError() {
-		c.HTML(200, orCtx.NewTemplate)
+		c.Success(orCtx.NewTemplate)
 		return
 	}
 
@@ -505,10 +507,10 @@ func DingtalkHooksEditPost(c *context.Context, f form.NewDingtalkHook) {
 	w.HookEvent = ParseHookEvent(f.Webhook)
 	w.IsActive = f.Active
 	if err := w.UpdateEvent(); err != nil {
-		c.Handle(500, "UpdateEvent", err)
+		c.Error(err, "update event")
 		return
 	} else if err := db.UpdateWebhook(w); err != nil {
-		c.Handle(500, "UpdateWebhook", err)
+		c.Error(err, "update webhook")
 		return
 	}
 
@@ -550,22 +552,22 @@ func TestWebhook(c *context.Context) {
 		author, err := db.GetUserByEmail(c.Repo.Commit.Author.Email)
 		if err == nil {
 			authorUsername = author.Name
-		} else if !errors.IsUserNotExist(err) {
-			c.Handle(500, "GetUserByEmail.(author)", err)
+		} else if !db.IsErrUserNotExist(err) {
+			c.Error(err, "get user by email")
 			return
 		}
 
 		user, err := db.GetUserByEmail(c.Repo.Commit.Committer.Email)
 		if err == nil {
 			committerUsername = user.Name
-		} else if !errors.IsUserNotExist(err) {
-			c.Handle(500, "GetUserByEmail.(committer)", err)
+		} else if !db.IsErrUserNotExist(err) {
+			c.Error(err, "get user by email")
 			return
 		}
 
 		nameStatus, err = c.Repo.Commit.ShowNameStatus()
 		if err != nil {
-			c.Handle(500, "FileStatus", err)
+			c.Error(err, "get changed files")
 			return
 		}
 	}
@@ -600,34 +602,36 @@ func TestWebhook(c *context.Context) {
 		Sender: apiUser,
 	}
 	if err := db.TestWebhook(c.Repo.Repository, db.HOOK_EVENT_PUSH, p, c.ParamsInt64("id")); err != nil {
-		c.Handle(500, "TestWebhook", err)
-	} else {
-		c.Flash.Info(c.Tr("repo.settings.webhook.test_delivery_success"))
-		c.Status(200)
+		c.Error(err, "test webhook")
+		return
 	}
+
+	c.Flash.Info(c.Tr("repo.settings.webhook.test_delivery_success"))
+	c.Status(http.StatusOK)
 }
 
 func RedeliveryWebhook(c *context.Context) {
 	webhook, err := db.GetWebhookOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
 	if err != nil {
-		c.NotFoundOrServerError("GetWebhookOfRepoByID/GetWebhookByOrgID", errors.IsWebhookNotExist, err)
+		c.NotFoundOrError(err, "get webhook")
 		return
 	}
 
 	hookTask, err := db.GetHookTaskOfWebhookByUUID(webhook.ID, c.Query("uuid"))
 	if err != nil {
-		c.NotFoundOrServerError("GetHookTaskOfWebhookByUUID/GetWebhookByOrgID", errors.IsHookTaskNotExist, err)
+		c.NotFoundOrError(err, "get hook task by UUID")
 		return
 	}
 
 	hookTask.IsDelivered = false
 	if err = db.UpdateHookTask(hookTask); err != nil {
-		c.Handle(500, "UpdateHookTask", err)
-	} else {
-		go db.HookQueue.Add(c.Repo.Repository.ID)
-		c.Flash.Info(c.Tr("repo.settings.webhook.redelivery_success", hookTask.UUID))
-		c.Status(200)
+		c.Error(err, "update hook task")
+		return
 	}
+
+	go db.HookQueue.Add(c.Repo.Repository.ID)
+	c.Flash.Info(c.Tr("repo.settings.webhook.redelivery_success", hookTask.UUID))
+	c.Status(http.StatusOK)
 }
 
 func DeleteWebhook(c *context.Context) {
@@ -637,7 +641,7 @@ func DeleteWebhook(c *context.Context) {
 		c.Flash.Success(c.Tr("repo.settings.webhook_deletion_success"))
 	}
 
-	c.JSON(200, map[string]interface{}{
+	c.JSONSuccess(map[string]interface{}{
 		"redirect": c.Repo.RepoLink + "/settings/hooks",
 	})
 }

+ 22 - 22
internal/route/repo/wiki.go

@@ -26,7 +26,7 @@ const (
 
 func MustEnableWiki(c *context.Context) {
 	if !c.Repo.Repository.EnableWiki {
-		c.Handle(404, "MustEnableWiki", nil)
+		c.NotFound()
 		return
 	}
 
@@ -45,12 +45,12 @@ type PageMeta struct {
 func renderWikiPage(c *context.Context, isViewPage bool) (*git.Repository, string) {
 	wikiRepo, err := git.Open(c.Repo.Repository.WikiPath())
 	if err != nil {
-		c.ServerError("open repository", err)
+		c.Error(err, "open repository")
 		return nil, ""
 	}
 	commit, err := wikiRepo.BranchCommit("master")
 	if err != nil {
-		c.ServerError("get branch commit", err)
+		c.Error(err, "get branch commit")
 		return nil, ""
 	}
 
@@ -58,7 +58,7 @@ func renderWikiPage(c *context.Context, isViewPage bool) (*git.Repository, strin
 	if isViewPage {
 		entries, err := commit.Entries()
 		if err != nil {
-			c.ServerError("list entries", err)
+			c.Error(err, "list entries")
 			return nil, ""
 		}
 		pages := make([]PageMeta, 0, len(entries))
@@ -91,13 +91,13 @@ func renderWikiPage(c *context.Context, isViewPage bool) (*git.Repository, strin
 		if gitutil.IsErrRevisionNotExist(err) {
 			c.Redirect(c.Repo.RepoLink + "/wiki/_pages")
 		} else {
-			c.ServerError("GetBlobByPath", err)
+			c.Error(err, "get blob")
 		}
 		return nil, ""
 	}
 	p, err := blob.Bytes()
 	if err != nil {
-		c.ServerError("Data", err)
+		c.Error(err, "read blob")
 		return nil, ""
 	}
 	if isViewPage {
@@ -114,7 +114,7 @@ func Wiki(c *context.Context) {
 
 	if !c.Repo.Repository.HasWiki() {
 		c.Data["Title"] = c.Tr("repo.wiki")
-		c.HTML(200, WIKI_START)
+		c.Success(WIKI_START)
 		return
 	}
 
@@ -126,12 +126,12 @@ func Wiki(c *context.Context) {
 	// Get last change information.
 	commits, err := wikiRepo.Log(git.RefsHeads+"master", git.LogOptions{Path: pageName + ".md"})
 	if err != nil {
-		c.ServerError("get commits by path", err)
+		c.Error(err, "get commits by path")
 		return
 	}
 	c.Data["Author"] = commits[0].Author
 
-	c.HTML(200, WIKI_VIEW)
+	c.Success(WIKI_VIEW)
 }
 
 func WikiPages(c *context.Context) {
@@ -145,18 +145,18 @@ func WikiPages(c *context.Context) {
 
 	wikiRepo, err := git.Open(c.Repo.Repository.WikiPath())
 	if err != nil {
-		c.ServerError("open repository", err)
+		c.Error(err, "open repository")
 		return
 	}
 	commit, err := wikiRepo.BranchCommit("master")
 	if err != nil {
-		c.ServerError("get branch commit", err)
+		c.Error(err, "get branch commit")
 		return
 	}
 
 	entries, err := commit.Entries()
 	if err != nil {
-		c.ServerError("list entries", err)
+		c.Error(err, "list entries")
 		return
 	}
 	pages := make([]PageMeta, 0, len(entries))
@@ -164,7 +164,7 @@ func WikiPages(c *context.Context) {
 		if entries[i].Type() == git.ObjectBlob && strings.HasSuffix(entries[i].Name(), ".md") {
 			commits, err := wikiRepo.Log(git.RefsHeads+"master", git.LogOptions{Path: entries[i].Name()})
 			if err != nil {
-				c.ServerError("get commits by path", err)
+				c.Error(err, "get commits by path")
 				return
 			}
 			name := strings.TrimSuffix(entries[i].Name(), ".md")
@@ -177,7 +177,7 @@ func WikiPages(c *context.Context) {
 	}
 	c.Data["Pages"] = pages
 
-	c.HTML(200, WIKI_PAGES)
+	c.Success(WIKI_PAGES)
 }
 
 func NewWiki(c *context.Context) {
@@ -189,7 +189,7 @@ func NewWiki(c *context.Context) {
 		c.Data["title"] = "Home"
 	}
 
-	c.HTML(200, WIKI_NEW)
+	c.Success(WIKI_NEW)
 }
 
 func NewWikiPost(c *context.Context, f form.NewWiki) {
@@ -198,7 +198,7 @@ func NewWikiPost(c *context.Context, f form.NewWiki) {
 	c.Data["RequireSimpleMDE"] = true
 
 	if c.HasError() {
-		c.HTML(200, WIKI_NEW)
+		c.Success(WIKI_NEW)
 		return
 	}
 
@@ -207,7 +207,7 @@ func NewWikiPost(c *context.Context, f form.NewWiki) {
 			c.Data["Err_Title"] = true
 			c.RenderWithErr(c.Tr("repo.wiki.page_already_exists"), WIKI_NEW, &f)
 		} else {
-			c.ServerError("AddWikiPage", err)
+			c.Error(err, "add wiki page")
 		}
 		return
 	}
@@ -230,7 +230,7 @@ func EditWiki(c *context.Context) {
 		return
 	}
 
-	c.HTML(200, WIKI_NEW)
+	c.Success(WIKI_NEW)
 }
 
 func EditWikiPost(c *context.Context, f form.NewWiki) {
@@ -239,12 +239,12 @@ func EditWikiPost(c *context.Context, f form.NewWiki) {
 	c.Data["RequireSimpleMDE"] = true
 
 	if c.HasError() {
-		c.HTML(200, WIKI_NEW)
+		c.Success(WIKI_NEW)
 		return
 	}
 
 	if err := c.Repo.Repository.EditWikiPage(c.User, f.OldTitle, f.Title, f.Content, f.Message); err != nil {
-		c.ServerError("EditWikiPage", err)
+		c.Error(err, "edit wiki page")
 		return
 	}
 
@@ -259,11 +259,11 @@ func DeleteWikiPagePost(c *context.Context) {
 
 	pageName := db.ToWikiPageName(pageURL)
 	if err := c.Repo.Repository.DeleteWikiPage(c.User, pageName); err != nil {
-		c.ServerError("DeleteWikiPage", err)
+		c.Error(err, "delete wiki page")
 		return
 	}
 
-	c.JSON(200, map[string]interface{}{
+	c.JSONSuccess(map[string]interface{}{
 		"redirect": c.Repo.RepoLink + "/wiki/",
 	})
 }

+ 34 - 34
internal/route/user/auth.go

@@ -53,8 +53,8 @@ func AutoLogin(c *context.Context) (bool, error) {
 
 	u, err := db.GetUserByName(uname)
 	if err != nil {
-		if !errors.IsUserNotExist(err) {
-			return false, fmt.Errorf("GetUserByName: %v", err)
+		if !db.IsErrUserNotExist(err) {
+			return false, fmt.Errorf("get user by name: %v", err)
 		}
 		return false, nil
 	}
@@ -79,7 +79,7 @@ func Login(c *context.Context) {
 	// Check auto-login
 	isSucceed, err := AutoLogin(c)
 	if err != nil {
-		c.ServerError("AutoLogin", err)
+		c.Error(err, "auto login")
 		return
 	}
 
@@ -94,7 +94,7 @@ func Login(c *context.Context) {
 		if tool.IsSameSiteURLPath(redirectTo) {
 			c.Redirect(redirectTo)
 		} else {
-			c.SubURLRedirect("/")
+			c.RedirectSubpath("/")
 		}
 		c.SetCookie("redirect_to", "", -1, conf.Server.Subpath)
 		return
@@ -103,7 +103,7 @@ func Login(c *context.Context) {
 	// Display normal login page
 	loginSources, err := db.ActivatedLoginSources()
 	if err != nil {
-		c.ServerError("ActivatedLoginSources", err)
+		c.Error(err, "list activated login sources")
 		return
 	}
 	c.Data["LoginSources"] = loginSources
@@ -142,7 +142,7 @@ func afterLogin(c *context.Context, u *db.User, remember bool) {
 		return
 	}
 
-	c.SubURLRedirect("/")
+	c.RedirectSubpath("/")
 }
 
 func LoginPost(c *context.Context, f form.SignIn) {
@@ -150,7 +150,7 @@ func LoginPost(c *context.Context, f form.SignIn) {
 
 	loginSources, err := db.ActivatedLoginSources()
 	if err != nil {
-		c.ServerError("ActivatedLoginSources", err)
+		c.Error(err, "list activated login sources")
 		return
 	}
 	c.Data["LoginSources"] = loginSources
@@ -163,7 +163,7 @@ func LoginPost(c *context.Context, f form.SignIn) {
 	u, err := db.UserLogin(f.UserName, f.Password, f.LoginSource)
 	if err != nil {
 		switch err.(type) {
-		case errors.UserNotExist:
+		case db.ErrUserNotExist:
 			c.FormErr("UserName", "Password")
 			c.RenderWithErr(c.Tr("form.username_password_incorrect"), LOGIN, &f)
 		case errors.LoginSourceMismatch:
@@ -171,7 +171,7 @@ func LoginPost(c *context.Context, f form.SignIn) {
 			c.RenderWithErr(c.Tr("form.auth_source_mismatch"), LOGIN, &f)
 
 		default:
-			c.ServerError("UserLogin", err)
+			c.Error(err, "authenticate user")
 		}
 		for i := range loginSources {
 			if loginSources[i].IsDefault {
@@ -189,7 +189,7 @@ func LoginPost(c *context.Context, f form.SignIn) {
 
 	c.Session.Set("twoFactorRemember", f.Remember)
 	c.Session.Set("twoFactorUserID", u.ID)
-	c.SubURLRedirect("/user/login/two_factor")
+	c.RedirectSubpath("/user/login/two_factor")
 }
 
 func LoginTwoFactor(c *context.Context) {
@@ -211,31 +211,31 @@ func LoginTwoFactorPost(c *context.Context) {
 
 	t, err := db.GetTwoFactorByUserID(userID)
 	if err != nil {
-		c.ServerError("GetTwoFactorByUserID", err)
+		c.Error(err, "get two factor by user ID")
 		return
 	}
 
 	passcode := c.Query("passcode")
 	valid, err := t.ValidateTOTP(passcode)
 	if err != nil {
-		c.ServerError("ValidateTOTP", err)
+		c.Error(err, "validate TOTP")
 		return
 	} else if !valid {
 		c.Flash.Error(c.Tr("settings.two_factor_invalid_passcode"))
-		c.SubURLRedirect("/user/login/two_factor")
+		c.RedirectSubpath("/user/login/two_factor")
 		return
 	}
 
 	u, err := db.GetUserByID(userID)
 	if err != nil {
-		c.ServerError("GetUserByID", err)
+		c.Error(err, "get user by ID")
 		return
 	}
 
 	// Prevent same passcode from being reused
 	if c.Cache.IsExist(u.TwoFactorCacheKey(passcode)) {
 		c.Flash.Error(c.Tr("settings.two_factor_reused_passcode"))
-		c.SubURLRedirect("/user/login/two_factor")
+		c.RedirectSubpath("/user/login/two_factor")
 		return
 	}
 	if err = c.Cache.Put(u.TwoFactorCacheKey(passcode), 1, 60); err != nil {
@@ -265,16 +265,16 @@ func LoginTwoFactorRecoveryCodePost(c *context.Context) {
 	if err := db.UseRecoveryCode(userID, c.Query("recovery_code")); err != nil {
 		if errors.IsTwoFactorRecoveryCodeNotFound(err) {
 			c.Flash.Error(c.Tr("auth.login_two_factor_invalid_recovery_code"))
-			c.SubURLRedirect("/user/login/two_factor_recovery_code")
+			c.RedirectSubpath("/user/login/two_factor_recovery_code")
 		} else {
-			c.ServerError("UseRecoveryCode", err)
+			c.Error(err, "use recovery code")
 		}
 		return
 	}
 
 	u, err := db.GetUserByID(userID)
 	if err != nil {
-		c.ServerError("GetUserByID", err)
+		c.Error(err, "get user by ID")
 		return
 	}
 	afterLogin(c, u, c.Session.Get("twoFactorRemember").(bool))
@@ -286,7 +286,7 @@ func SignOut(c *context.Context) {
 	c.SetCookie(conf.Security.CookieUsername, "", -1, conf.Server.Subpath)
 	c.SetCookie(conf.Security.CookieRememberName, "", -1, conf.Server.Subpath)
 	c.SetCookie(conf.Session.CSRFCookieName, "", -1, conf.Server.Subpath)
-	c.SubURLRedirect("/")
+	c.RedirectSubpath("/")
 }
 
 func SignUp(c *context.Context) {
@@ -351,7 +351,7 @@ func SignUpPost(c *context.Context, cpt *captcha.Captcha, f form.Register) {
 			c.FormErr("UserName")
 			c.RenderWithErr(c.Tr("user.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), SIGNUP, &f)
 		default:
-			c.ServerError("CreateUser", err)
+			c.Error(err, "create user")
 		}
 		return
 	}
@@ -362,7 +362,7 @@ func SignUpPost(c *context.Context, cpt *captcha.Captcha, f form.Register) {
 		u.IsAdmin = true
 		u.IsActive = true
 		if err := db.UpdateUser(u); err != nil {
-			c.ServerError("UpdateUser", err)
+			c.Error(err, "update user")
 			return
 		}
 	}
@@ -381,7 +381,7 @@ func SignUpPost(c *context.Context, cpt *captcha.Captcha, f form.Register) {
 		return
 	}
 
-	c.SubURLRedirect("/user/login")
+	c.RedirectSubpath("/user/login")
 }
 
 func Activate(c *context.Context) {
@@ -416,11 +416,11 @@ func Activate(c *context.Context) {
 		user.IsActive = true
 		var err error
 		if user.Rands, err = db.GetUserSalt(); err != nil {
-			c.ServerError("GetUserSalt", err)
+			c.Error(err, "get user salt")
 			return
 		}
 		if err := db.UpdateUser(user); err != nil {
-			c.ServerError("UpdateUser", err)
+			c.Error(err, "update user")
 			return
 		}
 
@@ -428,7 +428,7 @@ func Activate(c *context.Context) {
 
 		c.Session.Set("uid", user.ID)
 		c.Session.Set("uname", user.Name)
-		c.SubURLRedirect("/")
+		c.RedirectSubpath("/")
 		return
 	}
 
@@ -443,14 +443,14 @@ func ActivateEmail(c *context.Context) {
 	// Verify code.
 	if email := db.VerifyActiveEmailCode(code, emailAddr); email != nil {
 		if err := email.Activate(); err != nil {
-			c.ServerError("ActivateEmail", err)
+			c.Error(err, "activate email")
 		}
 
 		log.Trace("Email activated: %s", email.Email)
 		c.Flash.Success(c.Tr("settings.add_email_success"))
 	}
 
-	c.SubURLRedirect("/user/settings/email")
+	c.RedirectSubpath("/user/settings/email")
 }
 
 func ForgotPasswd(c *context.Context) {
@@ -480,14 +480,14 @@ func ForgotPasswdPost(c *context.Context) {
 
 	u, err := db.GetUserByEmail(emailAddr)
 	if err != nil {
-		if errors.IsUserNotExist(err) {
+		if db.IsErrUserNotExist(err) {
 			c.Data["Hours"] = conf.Auth.ActivateCodeLives / 60
 			c.Data["IsResetSent"] = true
 			c.Success(FORGOT_PASSWORD)
 			return
-		} else {
-			c.ServerError("GetUserByEmail", err)
 		}
+
+		c.Error(err, "get user by email")
 		return
 	}
 
@@ -549,21 +549,21 @@ func ResetPasswdPost(c *context.Context) {
 		u.Passwd = passwd
 		var err error
 		if u.Rands, err = db.GetUserSalt(); err != nil {
-			c.ServerError("GetUserSalt", err)
+			c.Error(err, "get user salt")
 			return
 		}
 		if u.Salt, err = db.GetUserSalt(); err != nil {
-			c.ServerError("GetUserSalt", err)
+			c.Error(err, "get user salt")
 			return
 		}
 		u.EncodePasswd()
 		if err := db.UpdateUser(u); err != nil {
-			c.ServerError("UpdateUser", err)
+			c.Error(err, "update user")
 			return
 		}
 
 		log.Trace("User password reset: %s", u.Name)
-		c.SubURLRedirect("/user/login")
+		c.RedirectSubpath("/user/login")
 		return
 	}
 

+ 31 - 31
internal/route/user/home.go

@@ -7,6 +7,7 @@ package user
 import (
 	"bytes"
 	"fmt"
+	"net/http"
 
 	"github.com/unknwon/com"
 	"github.com/unknwon/paginater"
@@ -14,7 +15,6 @@ import (
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/db/errors"
 )
 
 const (
@@ -33,7 +33,7 @@ func getDashboardContextUser(c *context.Context) *db.User {
 		// Organization.
 		org, err := db.GetUserByName(orgName)
 		if err != nil {
-			c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
+			c.NotFoundOrError(err, "get user by name")
 			return nil
 		}
 		ctxUser = org
@@ -41,7 +41,7 @@ func getDashboardContextUser(c *context.Context) *db.User {
 	c.Data["ContextUser"] = ctxUser
 
 	if err := c.User.GetOrganizations(true); err != nil {
-		c.Handle(500, "GetOrganizations", err)
+		c.Error(err, "get organizations")
 		return nil
 	}
 	c.Data["Orgs"] = c.User.Orgs
@@ -55,7 +55,7 @@ func getDashboardContextUser(c *context.Context) *db.User {
 func retrieveFeeds(c *context.Context, ctxUser *db.User, userID int64, isProfile bool) {
 	actions, err := db.GetFeeds(ctxUser, userID, c.QueryInt64("after_id"), isProfile)
 	if err != nil {
-		c.Handle(500, "GetFeeds", err)
+		c.Error(err, "get feeds")
 		return
 	}
 
@@ -68,10 +68,10 @@ func retrieveFeeds(c *context.Context, ctxUser *db.User, userID int64, isProfile
 		if !ok {
 			u, err := db.GetUserByName(act.ActUserName)
 			if err != nil {
-				if errors.IsUserNotExist(err) {
+				if db.IsErrUserNotExist(err) {
 					continue
 				}
-				c.Handle(500, "GetUserByName", err)
+				c.Error(err, "get user by name")
 				return
 			}
 			unameAvatars[act.ActUserName] = u.RelAvatarLink()
@@ -100,7 +100,7 @@ func Dashboard(c *context.Context) {
 	}
 
 	if c.Req.Header.Get("X-AJAX") == "true" {
-		c.HTML(200, NEWS_FEED)
+		c.Success(NEWS_FEED)
 		return
 	}
 
@@ -112,10 +112,10 @@ func Dashboard(c *context.Context) {
 	if !ctxUser.IsOrganization() {
 		collaborateRepos, err := c.User.GetAccessibleRepositories(conf.UI.User.RepoPagingNum)
 		if err != nil {
-			c.Handle(500, "GetAccessibleRepositories", err)
+			c.Error(err, "get accessible repositories")
 			return
 		} else if err = db.RepositoryList(collaborateRepos).LoadAttributes(); err != nil {
-			c.Handle(500, "RepositoryList.LoadAttributes", err)
+			c.Error(err, "load attributes")
 			return
 		}
 		c.Data["CollaborativeRepos"] = collaborateRepos
@@ -127,18 +127,18 @@ func Dashboard(c *context.Context) {
 	if ctxUser.IsOrganization() {
 		repos, repoCount, err = ctxUser.GetUserRepositories(c.User.ID, 1, conf.UI.User.RepoPagingNum)
 		if err != nil {
-			c.Handle(500, "GetUserRepositories", err)
+			c.Error(err, "get user repositories")
 			return
 		}
 
 		mirrors, err = ctxUser.GetUserMirrorRepositories(c.User.ID)
 		if err != nil {
-			c.Handle(500, "GetUserMirrorRepositories", err)
+			c.Error(err, "get user mirror repositories")
 			return
 		}
 	} else {
 		if err = ctxUser.GetRepositories(1, conf.UI.User.RepoPagingNum); err != nil {
-			c.Handle(500, "GetRepositories", err)
+			c.Error(err, "get repositories")
 			return
 		}
 		repos = ctxUser.Repos
@@ -146,7 +146,7 @@ func Dashboard(c *context.Context) {
 
 		mirrors, err = ctxUser.GetMirrorRepositories()
 		if err != nil {
-			c.Handle(500, "GetMirrorRepositories", err)
+			c.Error(err, "get mirror repositories")
 			return
 		}
 	}
@@ -155,13 +155,13 @@ func Dashboard(c *context.Context) {
 	c.Data["MaxShowRepoNum"] = conf.UI.User.RepoPagingNum
 
 	if err := db.MirrorRepositoryList(mirrors).LoadAttributes(); err != nil {
-		c.Handle(500, "MirrorRepositoryList.LoadAttributes", err)
+		c.Error(err, "load attributes")
 		return
 	}
 	c.Data["MirrorCount"] = len(mirrors)
 	c.Data["Mirrors"] = mirrors
 
-	c.HTML(200, DASHBOARD)
+	c.Success(DASHBOARD)
 }
 
 func Issues(c *context.Context) {
@@ -216,12 +216,12 @@ func Issues(c *context.Context) {
 	if ctxUser.IsOrganization() {
 		repos, _, err = ctxUser.GetUserRepositories(c.User.ID, 1, ctxUser.NumRepos)
 		if err != nil {
-			c.Handle(500, "GetRepositories", err)
+			c.Error(err, "get repositories")
 			return
 		}
 	} else {
 		if err := ctxUser.GetRepositories(1, c.User.NumRepos); err != nil {
-			c.Handle(500, "GetRepositories", err)
+			c.Error(err, "get repositories")
 			return
 		}
 		repos = ctxUser.Repos
@@ -255,7 +255,7 @@ func Issues(c *context.Context) {
 	if !isPullList {
 		userRepoIDs, err = db.FilterRepositoryWithIssues(userRepoIDs)
 		if err != nil {
-			c.Handle(500, "FilterRepositoryWithIssues", err)
+			c.Error(err, "filter repositories with issues")
 			return
 		}
 	}
@@ -287,32 +287,32 @@ func Issues(c *context.Context) {
 
 	issues, err := db.Issues(issueOptions)
 	if err != nil {
-		c.Handle(500, "Issues", err)
+		c.Error(err, "list issues")
 		return
 	}
 
 	if repoID > 0 {
 		repo, err := db.GetRepositoryByID(repoID)
 		if err != nil {
-			c.Handle(500, "GetRepositoryByID", fmt.Errorf("[#%d] %v", repoID, err))
+			c.Error(err, "get repository by ID")
 			return
 		}
 
 		if err = repo.GetOwner(); err != nil {
-			c.Handle(500, "GetOwner", fmt.Errorf("[#%d] %v", repoID, err))
+			c.Error(err, "get owner")
 			return
 		}
 
 		// Check if user has access to given repository.
 		if !repo.IsOwnedBy(ctxUser.ID) && !repo.HasAccess(ctxUser.ID) {
-			c.Handle(404, "Issues", fmt.Errorf("#%d", repoID))
+			c.NotFound()
 			return
 		}
 	}
 
 	for _, issue := range issues {
 		if err = issue.Repo.GetOwner(); err != nil {
-			c.Handle(500, "GetOwner", fmt.Errorf("[#%d] %v", issue.RepoID, err))
+			c.Error(err, "get owner")
 			return
 		}
 	}
@@ -341,13 +341,13 @@ func Issues(c *context.Context) {
 		c.Data["State"] = "open"
 	}
 
-	c.HTML(200, ISSUES)
+	c.Success(ISSUES)
 }
 
 func ShowSSHKeys(c *context.Context, uid int64) {
 	keys, err := db.ListPublicKeys(uid)
 	if err != nil {
-		c.Handle(500, "ListPublicKeys", err)
+		c.Error(err, "list public keys")
 		return
 	}
 
@@ -356,7 +356,7 @@ func ShowSSHKeys(c *context.Context, uid int64) {
 		buf.WriteString(keys[i].OmitEmail())
 		buf.WriteString("\n")
 	}
-	c.PlainText(200, buf.Bytes())
+	c.PlainText(http.StatusOK, buf.String())
 }
 
 func showOrgProfile(c *context.Context) {
@@ -382,7 +382,7 @@ func showOrgProfile(c *context.Context) {
 	if c.IsLogged && !c.User.IsAdmin {
 		repos, count, err = org.GetUserRepositories(c.User.ID, page, conf.UI.User.RepoPagingNum)
 		if err != nil {
-			c.Handle(500, "GetUserRepositories", err)
+			c.Error(err, "get user repositories")
 			return
 		}
 		c.Data["Repos"] = repos
@@ -395,7 +395,7 @@ func showOrgProfile(c *context.Context) {
 			PageSize: conf.UI.User.RepoPagingNum,
 		})
 		if err != nil {
-			c.Handle(500, "GetRepositories", err)
+			c.Error(err, "get user repositories")
 			return
 		}
 		c.Data["Repos"] = repos
@@ -404,20 +404,20 @@ func showOrgProfile(c *context.Context) {
 	c.Data["Page"] = paginater.New(int(count), conf.UI.User.RepoPagingNum, page, 5)
 
 	if err := org.GetMembers(); err != nil {
-		c.Handle(500, "GetMembers", err)
+		c.Error(err, "get members")
 		return
 	}
 	c.Data["Members"] = org.Members
 
 	c.Data["Teams"] = org.Teams
 
-	c.HTML(200, ORG_HOME)
+	c.Success(ORG_HOME)
 }
 
 func Email2User(c *context.Context) {
 	u, err := db.GetUserByEmail(c.Query("email"))
 	if err != nil {
-		c.NotFoundOrServerError("GetUserByEmail", errors.IsUserNotExist, err)
+		c.NotFoundOrError(err, "get user by email")
 		return
 	}
 	c.Redirect(conf.Server.Subpath + "/user/" + u.Name)

+ 7 - 8
internal/route/user/profile.go

@@ -5,15 +5,14 @@
 package user
 
 import (
-	"fmt"
-	repo2 "gogs.io/gogs/internal/route/repo"
 	"strings"
 
 	"github.com/unknwon/paginater"
 
+	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
-	"gogs.io/gogs/internal/conf"
+	"gogs.io/gogs/internal/route/repo"
 	"gogs.io/gogs/internal/tool"
 )
 
@@ -45,7 +44,7 @@ func Profile(c *context.Context, puser *context.ParamsUser) {
 
 	orgs, err := db.GetOrgsByUserID(puser.ID, c.IsLogged && (c.User.IsAdmin || c.User.ID == puser.ID))
 	if err != nil {
-		c.ServerError("GetOrgsByUserIDDesc", err)
+		c.Error(err, "get organizations by user ID")
 		return
 	}
 
@@ -73,7 +72,7 @@ func Profile(c *context.Context, puser *context.ParamsUser) {
 			PageSize: conf.UI.User.RepoPagingNum,
 		})
 		if err != nil {
-			c.ServerError("GetRepositories", err)
+			c.Error(err, "get user repositories")
 			return
 		}
 
@@ -89,7 +88,7 @@ func Followers(c *context.Context, puser *context.ParamsUser) {
 	c.PageIs("Followers")
 	c.Data["CardsTitle"] = c.Tr("user.followers")
 	c.Data["Owner"] = puser
-	repo2.RenderUserCards(c, puser.NumFollowers, puser.GetFollowers, FOLLOWERS)
+	repo.RenderUserCards(c, puser.NumFollowers, puser.GetFollowers, FOLLOWERS)
 }
 
 func Following(c *context.Context, puser *context.ParamsUser) {
@@ -97,7 +96,7 @@ func Following(c *context.Context, puser *context.ParamsUser) {
 	c.PageIs("Following")
 	c.Data["CardsTitle"] = c.Tr("user.following")
 	c.Data["Owner"] = puser
-	repo2.RenderUserCards(c, puser.NumFollowing, puser.GetFollowing, FOLLOWERS)
+	repo.RenderUserCards(c, puser.NumFollowing, puser.GetFollowing, FOLLOWERS)
 }
 
 func Stars(c *context.Context) {
@@ -114,7 +113,7 @@ func Action(c *context.Context, puser *context.ParamsUser) {
 	}
 
 	if err != nil {
-		c.ServerError(fmt.Sprintf("Action (%s)", c.Params(":action")), err)
+		c.Errorf(err, "action %q", c.Params(":action"))
 		return
 	}
 

+ 44 - 44
internal/route/user/setting.go

@@ -80,7 +80,7 @@ func SettingsPost(c *context.Context, f form.UpdateProfile) {
 				case db.IsErrNamePatternNotAllowed(err):
 					msg = c.Tr("form.name_pattern_not_allowed")
 				default:
-					c.ServerError("ChangeUserName", err)
+					c.Error(err, "change user name")
 					return
 				}
 
@@ -106,12 +106,12 @@ func SettingsPost(c *context.Context, f form.UpdateProfile) {
 			c.RenderWithErr(msg, SETTINGS_PROFILE, &f)
 			return
 		}
-		c.ServerError("UpdateUser", err)
+		c.Errorf(err, "update user")
 		return
 	}
 
 	c.Flash.Success(c.Tr("settings.update_profile_success"))
-	c.SubURLRedirect("/user/settings")
+	c.RedirectSubpath("/user/settings")
 }
 
 // FIXME: limit upload size
@@ -169,7 +169,7 @@ func SettingsAvatarPost(c *context.Context, f form.Avatar) {
 		c.Flash.Success(c.Tr("settings.update_avatar_success"))
 	}
 
-	c.SubURLRedirect("/user/settings/avatar")
+	c.RedirectSubpath("/user/settings/avatar")
 }
 
 func SettingsDeleteAvatar(c *context.Context) {
@@ -177,7 +177,7 @@ func SettingsDeleteAvatar(c *context.Context) {
 		c.Flash.Error(fmt.Sprintf("Failed to delete avatar: %v", err))
 	}
 
-	c.SubURLRedirect("/user/settings/avatar")
+	c.RedirectSubpath("/user/settings/avatar")
 }
 
 func SettingsPassword(c *context.Context) {
@@ -203,18 +203,18 @@ func SettingsPasswordPost(c *context.Context, f form.ChangePassword) {
 		c.User.Passwd = f.Password
 		var err error
 		if c.User.Salt, err = db.GetUserSalt(); err != nil {
-			c.ServerError("GetUserSalt", err)
+			c.Errorf(err, "get user salt")
 			return
 		}
 		c.User.EncodePasswd()
 		if err := db.UpdateUser(c.User); err != nil {
-			c.ServerError("UpdateUser", err)
+			c.Errorf(err, "update user")
 			return
 		}
 		c.Flash.Success(c.Tr("settings.change_password_success"))
 	}
 
-	c.SubURLRedirect("/user/settings/password")
+	c.RedirectSubpath("/user/settings/password")
 }
 
 func SettingsEmails(c *context.Context) {
@@ -223,7 +223,7 @@ func SettingsEmails(c *context.Context) {
 
 	emails, err := db.GetEmailAddresses(c.User.ID)
 	if err != nil {
-		c.ServerError("GetEmailAddresses", err)
+		c.Errorf(err, "get email addresses")
 		return
 	}
 	c.Data["Emails"] = emails
@@ -238,18 +238,18 @@ func SettingsEmailPost(c *context.Context, f form.AddEmail) {
 	// Make emailaddress primary.
 	if c.Query("_method") == "PRIMARY" {
 		if err := db.MakeEmailPrimary(c.UserID(), &db.EmailAddress{ID: c.QueryInt64("id")}); err != nil {
-			c.ServerError("MakeEmailPrimary", err)
+			c.Errorf(err, "make email primary")
 			return
 		}
 
-		c.SubURLRedirect("/user/settings/email")
+		c.RedirectSubpath("/user/settings/email")
 		return
 	}
 
 	// Add Email address.
 	emails, err := db.GetEmailAddresses(c.User.ID)
 	if err != nil {
-		c.ServerError("GetEmailAddresses", err)
+		c.Errorf(err, "get email addresses")
 		return
 	}
 	c.Data["Emails"] = emails
@@ -268,7 +268,7 @@ func SettingsEmailPost(c *context.Context, f form.AddEmail) {
 		if db.IsErrEmailAlreadyUsed(err) {
 			c.RenderWithErr(c.Tr("form.email_been_used"), SETTINGS_EMAILS, &f)
 		} else {
-			c.ServerError("AddEmailAddress", err)
+			c.Errorf(err, "add email address")
 		}
 		return
 	}
@@ -285,7 +285,7 @@ func SettingsEmailPost(c *context.Context, f form.AddEmail) {
 		c.Flash.Success(c.Tr("settings.add_email_success"))
 	}
 
-	c.SubURLRedirect("/user/settings/email")
+	c.RedirectSubpath("/user/settings/email")
 }
 
 func DeleteEmail(c *context.Context) {
@@ -293,7 +293,7 @@ func DeleteEmail(c *context.Context) {
 		ID:  c.QueryInt64("id"),
 		UID: c.User.ID,
 	}); err != nil {
-		c.ServerError("DeleteEmailAddress", err)
+		c.Errorf(err, "delete email address")
 		return
 	}
 
@@ -309,7 +309,7 @@ func SettingsSSHKeys(c *context.Context) {
 
 	keys, err := db.ListPublicKeys(c.User.ID)
 	if err != nil {
-		c.ServerError("ListPublicKeys", err)
+		c.Errorf(err, "list public keys")
 		return
 	}
 	c.Data["Keys"] = keys
@@ -323,7 +323,7 @@ func SettingsSSHKeysPost(c *context.Context, f form.AddSSHKey) {
 
 	keys, err := db.ListPublicKeys(c.User.ID)
 	if err != nil {
-		c.ServerError("ListPublicKeys", err)
+		c.Errorf(err, "list public keys")
 		return
 	}
 	c.Data["Keys"] = keys
@@ -339,7 +339,7 @@ func SettingsSSHKeysPost(c *context.Context, f form.AddSSHKey) {
 			c.Flash.Info(c.Tr("form.unable_verify_ssh_key"))
 		} else {
 			c.Flash.Error(c.Tr("form.invalid_ssh_key", err.Error()))
-			c.SubURLRedirect("/user/settings/ssh")
+			c.RedirectSubpath("/user/settings/ssh")
 			return
 		}
 	}
@@ -354,13 +354,13 @@ func SettingsSSHKeysPost(c *context.Context, f form.AddSSHKey) {
 			c.FormErr("Title")
 			c.RenderWithErr(c.Tr("settings.ssh_key_name_used"), SETTINGS_SSH_KEYS, &f)
 		default:
-			c.ServerError("AddPublicKey", err)
+			c.Errorf(err, "add public key")
 		}
 		return
 	}
 
 	c.Flash.Success(c.Tr("settings.add_key_success", f.Title))
-	c.SubURLRedirect("/user/settings/ssh")
+	c.RedirectSubpath("/user/settings/ssh")
 }
 
 func DeleteSSHKey(c *context.Context) {
@@ -381,7 +381,7 @@ func SettingsSecurity(c *context.Context) {
 
 	t, err := db.GetTwoFactorByUserID(c.UserID())
 	if err != nil && !errors.IsTwoFactorNotFound(err) {
-		c.ServerError("GetTwoFactorByUserID", err)
+		c.Errorf(err, "get two factor by user ID")
 		return
 	}
 	c.Data["TwoFactor"] = t
@@ -410,7 +410,7 @@ func SettingsTwoFactorEnable(c *context.Context) {
 			AccountName: c.User.Email,
 		})
 		if err != nil {
-			c.ServerError("Generate", err)
+			c.Errorf(err, "generate TOTP")
 			return
 		}
 	}
@@ -418,13 +418,13 @@ func SettingsTwoFactorEnable(c *context.Context) {
 
 	img, err := key.Image(240, 240)
 	if err != nil {
-		c.ServerError("Image", err)
+		c.Errorf(err, "generate image")
 		return
 	}
 
 	var buf bytes.Buffer
 	if err = png.Encode(&buf, img); err != nil {
-		c.ServerError("Encode", err)
+		c.Errorf(err, "encode image")
 		return
 	}
 	c.Data["QRCode"] = template.URL("data:image/png;base64," + base64.StdEncoding.EncodeToString(buf.Bytes()))
@@ -443,20 +443,20 @@ func SettingsTwoFactorEnablePost(c *context.Context) {
 
 	if !totp.Validate(c.Query("passcode"), secret) {
 		c.Flash.Error(c.Tr("settings.two_factor_invalid_passcode"))
-		c.SubURLRedirect("/user/settings/security/two_factor_enable")
+		c.RedirectSubpath("/user/settings/security/two_factor_enable")
 		return
 	}
 
 	if err := db.NewTwoFactor(c.UserID(), secret); err != nil {
 		c.Flash.Error(c.Tr("settings.two_factor_enable_error", err))
-		c.SubURLRedirect("/user/settings/security/two_factor_enable")
+		c.RedirectSubpath("/user/settings/security/two_factor_enable")
 		return
 	}
 
 	c.Session.Delete("twoFactorSecret")
 	c.Session.Delete("twoFactorURL")
 	c.Flash.Success(c.Tr("settings.two_factor_enable_success"))
-	c.SubURLRedirect("/user/settings/security/two_factor_recovery_codes")
+	c.RedirectSubpath("/user/settings/security/two_factor_recovery_codes")
 }
 
 func SettingsTwoFactorRecoveryCodes(c *context.Context) {
@@ -470,7 +470,7 @@ func SettingsTwoFactorRecoveryCodes(c *context.Context) {
 
 	recoveryCodes, err := db.GetRecoveryCodesByUserID(c.UserID())
 	if err != nil {
-		c.ServerError("GetRecoveryCodesByUserID", err)
+		c.Errorf(err, "get recovery codes by user ID")
 		return
 	}
 	c.Data["RecoveryCodes"] = recoveryCodes
@@ -490,7 +490,7 @@ func SettingsTwoFactorRecoveryCodesPost(c *context.Context) {
 		c.Flash.Success(c.Tr("settings.two_factor_regenerate_recovery_codes_success"))
 	}
 
-	c.SubURLRedirect("/user/settings/security/two_factor_recovery_codes")
+	c.RedirectSubpath("/user/settings/security/two_factor_recovery_codes")
 }
 
 func SettingsTwoFactorDisable(c *context.Context) {
@@ -500,7 +500,7 @@ func SettingsTwoFactorDisable(c *context.Context) {
 	}
 
 	if err := db.DeleteTwoFactor(c.UserID()); err != nil {
-		c.ServerError("DeleteTwoFactor", err)
+		c.Errorf(err, "delete two factor")
 		return
 	}
 
@@ -516,11 +516,11 @@ func SettingsRepos(c *context.Context) {
 
 	repos, err := db.GetUserAndCollaborativeRepositories(c.User.ID)
 	if err != nil {
-		c.ServerError("GetUserAndCollaborativeRepositories", err)
+		c.Errorf(err, "get user and collaborative repositories")
 		return
 	}
 	if err = db.RepositoryList(repos).LoadAttributes(); err != nil {
-		c.ServerError("LoadAttributes", err)
+		c.Errorf(err, "load attributes")
 		return
 	}
 	c.Data["Repos"] = repos
@@ -531,12 +531,12 @@ func SettingsRepos(c *context.Context) {
 func SettingsLeaveRepo(c *context.Context) {
 	repo, err := db.GetRepositoryByID(c.QueryInt64("id"))
 	if err != nil {
-		c.NotFoundOrServerError("GetRepositoryByID", errors.IsRepoNotExist, err)
+		c.NotFoundOrError(err, "get repository by ID")
 		return
 	}
 
 	if err = repo.DeleteCollaboration(c.User.ID); err != nil {
-		c.ServerError("DeleteCollaboration", err)
+		c.Errorf(err, "delete collaboration")
 		return
 	}
 
@@ -552,7 +552,7 @@ func SettingsOrganizations(c *context.Context) {
 
 	orgs, err := db.GetOrgsByUserID(c.User.ID, true)
 	if err != nil {
-		c.ServerError("GetOrgsByUserID", err)
+		c.Errorf(err, "get organizations by user ID")
 		return
 	}
 	c.Data["Orgs"] = orgs
@@ -565,7 +565,7 @@ func SettingsLeaveOrganization(c *context.Context) {
 		if db.IsErrLastOrgOwner(err) {
 			c.Flash.Error(c.Tr("form.last_org_owner"))
 		} else {
-			c.ServerError("RemoveOrgUser", err)
+			c.Errorf(err, "remove organization user")
 			return
 		}
 	}
@@ -581,7 +581,7 @@ func SettingsApplications(c *context.Context) {
 
 	tokens, err := db.ListAccessTokens(c.User.ID)
 	if err != nil {
-		c.ServerError("ListAccessTokens", err)
+		c.Errorf(err, "list access tokens")
 		return
 	}
 	c.Data["Tokens"] = tokens
@@ -596,7 +596,7 @@ func SettingsApplicationsPost(c *context.Context, f form.NewAccessToken) {
 	if c.HasError() {
 		tokens, err := db.ListAccessTokens(c.User.ID)
 		if err != nil {
-			c.ServerError("ListAccessTokens", err)
+			c.Errorf(err, "list access tokens")
 			return
 		}
 
@@ -612,16 +612,16 @@ func SettingsApplicationsPost(c *context.Context, f form.NewAccessToken) {
 	if err := db.NewAccessToken(t); err != nil {
 		if errors.IsAccessTokenNameAlreadyExist(err) {
 			c.Flash.Error(c.Tr("settings.token_name_exists"))
-			c.SubURLRedirect("/user/settings/applications")
+			c.RedirectSubpath("/user/settings/applications")
 		} else {
-			c.ServerError("NewAccessToken", err)
+			c.Errorf(err, "new access token")
 		}
 		return
 	}
 
 	c.Flash.Success(c.Tr("settings.generate_token_succees"))
 	c.Flash.Info(t.Sha1)
-	c.SubURLRedirect("/user/settings/applications")
+	c.RedirectSubpath("/user/settings/applications")
 }
 
 func SettingsDeleteApplication(c *context.Context) {
@@ -642,10 +642,10 @@ func SettingsDelete(c *context.Context) {
 
 	if c.Req.Method == "POST" {
 		if _, err := db.UserLogin(c.User.Name, c.Query("password"), c.User.LoginSource); err != nil {
-			if errors.IsUserNotExist(err) {
+			if db.IsErrUserNotExist(err) {
 				c.RenderWithErr(c.Tr("form.enterred_invalid_password"), SETTINGS_DELETE, nil)
 			} else {
-				c.ServerError("UserLogin", err)
+				c.Errorf(err, "authenticate user")
 			}
 			return
 		}
@@ -659,7 +659,7 @@ func SettingsDelete(c *context.Context) {
 				c.Flash.Error(c.Tr("form.still_has_org"))
 				c.Redirect(conf.Server.Subpath + "/user/settings/delete")
 			default:
-				c.ServerError("DeleteUser", err)
+				c.Errorf(err, "delete user")
 			}
 		} else {
 			log.Trace("Account deleted: %s", c.User.Name)

+ 1 - 0
internal/template/template.go

@@ -256,6 +256,7 @@ func ActionContent2Commits(act Actioner) *db.PushCommits {
 	return push
 }
 
+// TODO(unknwon): Use url.Escape.
 func EscapePound(str string) string {
 	return strings.NewReplacer("%", "%25", "#", "%23", " ", "%20", "?", "%3F").Replace(str)
 }

Some files were not shown because too many files changed in this diff