aboutsummaryrefslogtreecommitdiff
path: root/routes/repo
diff options
context:
space:
mode:
Diffstat (limited to 'routes/repo')
-rw-r--r--routes/repo/branch.go155
-rw-r--r--routes/repo/commit.go236
-rw-r--r--routes/repo/download.go68
-rw-r--r--routes/repo/editor.go574
-rw-r--r--routes/repo/http.go424
-rw-r--r--routes/repo/issue.go1278
-rw-r--r--routes/repo/pull.go771
-rw-r--r--routes/repo/release.go332
-rw-r--r--routes/repo/repo.go342
-rw-r--r--routes/repo/setting.go695
-rw-r--r--routes/repo/view.go371
-rw-r--r--routes/repo/webhook.go629
-rw-r--r--routes/repo/wiki.go274
13 files changed, 0 insertions, 6149 deletions
diff --git a/routes/repo/branch.go b/routes/repo/branch.go
deleted file mode 100644
index 96308616..00000000
--- a/routes/repo/branch.go
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2014 The Gogs Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package repo
-
-import (
- "time"
-
- log "gopkg.in/clog.v1"
-
- "github.com/gogs/git-module"
- api "github.com/gogs/go-gogs-client"
-
- "gogs.io/gogs/models"
- "gogs.io/gogs/pkg/context"
- "gogs.io/gogs/pkg/tool"
-)
-
-const (
- BRANCHES_OVERVIEW = "repo/branches/overview"
- BRANCHES_ALL = "repo/branches/all"
-)
-
-type Branch struct {
- Name string
- Commit *git.Commit
- IsProtected bool
-}
-
-func loadBranches(c *context.Context) []*Branch {
- rawBranches, err := c.Repo.Repository.GetBranches()
- if err != nil {
- c.Handle(500, "GetBranches", err)
- return nil
- }
-
- protectBranches, err := models.GetProtectBranchesByRepoID(c.Repo.Repository.ID)
- if err != nil {
- c.Handle(500, "GetProtectBranchesByRepoID", err)
- return nil
- }
-
- branches := make([]*Branch, len(rawBranches))
- for i := range rawBranches {
- commit, err := rawBranches[i].GetCommit()
- if err != nil {
- c.Handle(500, "GetCommit", err)
- return nil
- }
-
- branches[i] = &Branch{
- Name: rawBranches[i].Name,
- Commit: commit,
- }
-
- for j := range protectBranches {
- if branches[i].Name == protectBranches[j].Name {
- branches[i].IsProtected = true
- break
- }
- }
- }
-
- c.Data["AllowPullRequest"] = c.Repo.Repository.AllowsPulls()
- return branches
-}
-
-func Branches(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.git_branches")
- c.Data["PageIsBranchesOverview"] = true
-
- branches := loadBranches(c)
- if c.Written() {
- return
- }
-
- now := time.Now()
- activeBranches := make([]*Branch, 0, 3)
- staleBranches := make([]*Branch, 0, 3)
- for i := range branches {
- switch {
- case branches[i].Name == c.Repo.BranchName:
- c.Data["DefaultBranch"] = branches[i]
- case branches[i].Commit.Committer.When.Add(30 * 24 * time.Hour).After(now): // 30 days
- activeBranches = append(activeBranches, branches[i])
- case branches[i].Commit.Committer.When.Add(3 * 30 * 24 * time.Hour).Before(now): // 90 days
- staleBranches = append(staleBranches, branches[i])
- }
- }
-
- c.Data["ActiveBranches"] = activeBranches
- c.Data["StaleBranches"] = staleBranches
- c.HTML(200, BRANCHES_OVERVIEW)
-}
-
-func AllBranches(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.git_branches")
- c.Data["PageIsBranchesAll"] = true
-
- branches := loadBranches(c)
- if c.Written() {
- return
- }
- c.Data["Branches"] = branches
-
- c.HTML(200, BRANCHES_ALL)
-}
-
-func DeleteBranchPost(c *context.Context) {
- branchName := c.Params("*")
- commitID := c.Query("commit")
-
- defer func() {
- redirectTo := c.Query("redirect_to")
- if !tool.IsSameSiteURLPath(redirectTo) {
- redirectTo = c.Repo.RepoLink
- }
- c.Redirect(redirectTo)
- }()
-
- if !c.Repo.GitRepo.IsBranchExist(branchName) {
- return
- }
- if len(commitID) > 0 {
- branchCommitID, err := c.Repo.GitRepo.GetBranchCommitID(branchName)
- if err != nil {
- log.Error(2, "Failed to get commit ID of branch %q: %v", branchName, err)
- return
- }
-
- if branchCommitID != commitID {
- c.Flash.Error(c.Tr("repo.pulls.delete_branch_has_new_commits"))
- return
- }
- }
-
- if err := c.Repo.GitRepo.DeleteBranch(branchName, git.DeleteBranchOptions{
- Force: true,
- }); err != nil {
- log.Error(2, "Failed to delete branch %q: %v", branchName, err)
- return
- }
-
- if err := models.PrepareWebhooks(c.Repo.Repository, models.HOOK_EVENT_DELETE, &api.DeletePayload{
- Ref: branchName,
- RefType: "branch",
- PusherType: api.PUSHER_TYPE_USER,
- Repo: c.Repo.Repository.APIFormat(nil),
- Sender: c.User.APIFormat(),
- }); err != nil {
- log.Error(2, "Failed to prepare webhooks for %q: %v", models.HOOK_EVENT_DELETE, err)
- return
- }
-}
diff --git a/routes/repo/commit.go b/routes/repo/commit.go
deleted file mode 100644
index 504f76b8..00000000
--- a/routes/repo/commit.go
+++ /dev/null
@@ -1,236 +0,0 @@
-// Copyright 2014 The Gogs Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package repo
-
-import (
- "container/list"
- "path"
-
- "github.com/gogs/git-module"
-
- "gogs.io/gogs/models"
- "gogs.io/gogs/pkg/context"
- "gogs.io/gogs/pkg/setting"
- "gogs.io/gogs/pkg/tool"
-)
-
-const (
- COMMITS = "repo/commits"
- DIFF = "repo/diff/page"
-)
-
-func RefCommits(c *context.Context) {
- c.Data["PageIsViewFiles"] = true
- switch {
- case len(c.Repo.TreePath) == 0:
- Commits(c)
- case c.Repo.TreePath == "search":
- SearchCommits(c)
- default:
- FileHistory(c)
- }
-}
-
-func RenderIssueLinks(oldCommits *list.List, repoLink string) *list.List {
- newCommits := list.New()
- for e := oldCommits.Front(); e != nil; e = e.Next() {
- c := e.Value.(*git.Commit)
- newCommits.PushBack(c)
- }
- return newCommits
-}
-
-func renderCommits(c *context.Context, filename string) {
- c.Data["Title"] = c.Tr("repo.commits.commit_history") + " · " + c.Repo.Repository.FullName()
- c.Data["PageIsCommits"] = true
- c.Data["FileName"] = filename
-
- page := c.QueryInt("page")
- if page < 1 {
- page = 1
- }
- pageSize := c.QueryInt("pageSize")
- if pageSize < 1 {
- pageSize = git.DefaultCommitsPageSize
- }
-
- // Both 'git log branchName' and 'git log commitID' work.
- var err error
- var commits *list.List
- if len(filename) == 0 {
- commits, err = c.Repo.Commit.CommitsByRangeSize(page, pageSize)
- } else {
- commits, err = c.Repo.GitRepo.CommitsByFileAndRangeSize(c.Repo.BranchName, filename, page, pageSize)
- }
- if err != nil {
- c.Handle(500, "CommitsByRangeSize/CommitsByFileAndRangeSize", err)
- return
- }
- commits = RenderIssueLinks(commits, c.Repo.RepoLink)
- commits = models.ValidateCommitsWithEmails(commits)
- c.Data["Commits"] = commits
-
- if page > 1 {
- c.Data["HasPrevious"] = true
- c.Data["PreviousPage"] = page - 1
- }
- if commits.Len() == pageSize {
- c.Data["HasNext"] = true
- c.Data["NextPage"] = page + 1
- }
- c.Data["PageSize"] = pageSize
-
- c.Data["Username"] = c.Repo.Owner.Name
- c.Data["Reponame"] = c.Repo.Repository.Name
- c.HTML(200, COMMITS)
-}
-
-func Commits(c *context.Context) {
- renderCommits(c, "")
-}
-
-func SearchCommits(c *context.Context) {
- c.Data["PageIsCommits"] = true
-
- keyword := c.Query("q")
- if len(keyword) == 0 {
- c.Redirect(c.Repo.RepoLink + "/commits/" + c.Repo.BranchName)
- return
- }
-
- commits, err := c.Repo.Commit.SearchCommits(keyword)
- if err != nil {
- c.Handle(500, "SearchCommits", err)
- return
- }
- commits = RenderIssueLinks(commits, c.Repo.RepoLink)
- commits = models.ValidateCommitsWithEmails(commits)
- c.Data["Commits"] = commits
-
- c.Data["Keyword"] = keyword
- c.Data["Username"] = c.Repo.Owner.Name
- c.Data["Reponame"] = c.Repo.Repository.Name
- c.Data["Branch"] = c.Repo.BranchName
- c.HTML(200, COMMITS)
-}
-
-func FileHistory(c *context.Context) {
- renderCommits(c, c.Repo.TreePath)
-}
-
-func Diff(c *context.Context) {
- c.PageIs("Diff")
- c.RequireHighlightJS()
-
- userName := c.Repo.Owner.Name
- repoName := c.Repo.Repository.Name
- commitID := c.Params(":sha")
-
- commit, err := c.Repo.GitRepo.GetCommit(commitID)
- if err != nil {
- c.NotFoundOrServerError("get commit by ID", git.IsErrNotExist, err)
- return
- }
-
- diff, err := models.GetDiffCommit(models.RepoPath(userName, repoName),
- commitID, setting.Git.MaxGitDiffLines,
- setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles)
- if err != nil {
- c.NotFoundOrServerError("get diff commit", git.IsErrNotExist, err)
- return
- }
-
- parents := make([]string, commit.ParentCount())
- for i := 0; i < commit.ParentCount(); i++ {
- sha, err := commit.ParentID(i)
- parents[i] = sha.String()
- if err != nil {
- c.NotFound()
- return
- }
- }
-
- setEditorconfigIfExists(c)
- if c.Written() {
- return
- }
-
- c.Title(commit.Summary() + " · " + tool.ShortSHA1(commitID))
- c.Data["CommitID"] = commitID
- c.Data["IsSplitStyle"] = c.Query("style") == "split"
- c.Data["Username"] = userName
- c.Data["Reponame"] = repoName
- c.Data["IsImageFile"] = commit.IsImageFile
- c.Data["Commit"] = commit
- c.Data["Author"] = models.ValidateCommitWithEmail(commit)
- c.Data["Diff"] = diff
- c.Data["Parents"] = parents
- c.Data["DiffNotAvailable"] = diff.NumFiles() == 0
- c.Data["SourcePath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "src", commitID)
- if commit.ParentCount() > 0 {
- c.Data["BeforeSourcePath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "src", parents[0])
- }
- c.Data["RawPath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "raw", commitID)
- c.Success(DIFF)
-}
-
-func RawDiff(c *context.Context) {
- if err := git.GetRawDiff(
- models.RepoPath(c.Repo.Owner.Name, c.Repo.Repository.Name),
- c.Params(":sha"),
- git.RawDiffType(c.Params(":ext")),
- c.Resp,
- ); err != nil {
- c.NotFoundOrServerError("GetRawDiff", git.IsErrNotExist, err)
- return
- }
-}
-
-func CompareDiff(c *context.Context) {
- c.Data["IsDiffCompare"] = true
- userName := c.Repo.Owner.Name
- repoName := c.Repo.Repository.Name
- beforeCommitID := c.Params(":before")
- afterCommitID := c.Params(":after")
-
- commit, err := c.Repo.GitRepo.GetCommit(afterCommitID)
- if err != nil {
- c.Handle(404, "GetCommit", err)
- return
- }
-
- diff, err := models.GetDiffRange(models.RepoPath(userName, repoName), beforeCommitID,
- afterCommitID, setting.Git.MaxGitDiffLines,
- setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles)
- if err != nil {
- c.Handle(404, "GetDiffRange", err)
- return
- }
-
- commits, err := commit.CommitsBeforeUntil(beforeCommitID)
- if err != nil {
- c.Handle(500, "CommitsBeforeUntil", err)
- return
- }
- commits = models.ValidateCommitsWithEmails(commits)
-
- c.Data["IsSplitStyle"] = c.Query("style") == "split"
- c.Data["CommitRepoLink"] = c.Repo.RepoLink
- c.Data["Commits"] = commits
- c.Data["CommitsCount"] = commits.Len()
- c.Data["BeforeCommitID"] = beforeCommitID
- c.Data["AfterCommitID"] = afterCommitID
- c.Data["Username"] = userName
- c.Data["Reponame"] = repoName
- c.Data["IsImageFile"] = commit.IsImageFile
- c.Data["Title"] = "Comparing " + tool.ShortSHA1(beforeCommitID) + "..." + tool.ShortSHA1(afterCommitID) + " · " + userName + "/" + repoName
- c.Data["Commit"] = commit
- c.Data["Diff"] = diff
- c.Data["DiffNotAvailable"] = diff.NumFiles() == 0
- c.Data["SourcePath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "src", afterCommitID)
- c.Data["BeforeSourcePath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "src", beforeCommitID)
- c.Data["RawPath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "raw", afterCommitID)
- c.HTML(200, DIFF)
-}
diff --git a/routes/repo/download.go b/routes/repo/download.go
deleted file mode 100644
index 9b90a017..00000000
--- a/routes/repo/download.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2014 The Gogs Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package repo
-
-import (
- "fmt"
- "io"
- "net/http"
- "path"
-
- "github.com/gogs/git-module"
-
- "gogs.io/gogs/pkg/context"
- "gogs.io/gogs/pkg/setting"
- "gogs.io/gogs/pkg/tool"
-)
-
-func ServeData(c *context.Context, name string, reader io.Reader) error {
- buf := make([]byte, 1024)
- n, _ := reader.Read(buf)
- if n >= 0 {
- buf = buf[:n]
- }
-
- commit, err := c.Repo.Commit.GetCommitByPath(c.Repo.TreePath)
- if err != nil {
- return fmt.Errorf("GetCommitByPath: %v", err)
- }
- c.Resp.Header().Set("Last-Modified", commit.Committer.When.Format(http.TimeFormat))
-
- if !tool.IsTextFile(buf) {
- if !tool.IsImageFile(buf) {
- c.Resp.Header().Set("Content-Disposition", "attachment; filename=\""+name+"\"")
- c.Resp.Header().Set("Content-Transfer-Encoding", "binary")
- }
- } else if !setting.Repository.EnableRawFileRenderMode || !c.QueryBool("render") {
- c.Resp.Header().Set("Content-Type", "text/plain; charset=utf-8")
- }
- c.Resp.Write(buf)
- _, err = io.Copy(c.Resp, reader)
- return err
-}
-
-func ServeBlob(c *context.Context, blob *git.Blob) error {
- dataRc, err := blob.Data()
- if err != nil {
- return err
- }
-
- return ServeData(c, path.Base(c.Repo.TreePath), dataRc)
-}
-
-func SingleDownload(c *context.Context) {
- blob, err := c.Repo.Commit.GetBlobByPath(c.Repo.TreePath)
- if err != nil {
- if git.IsErrNotExist(err) {
- c.Handle(404, "GetBlobByPath", nil)
- } else {
- c.Handle(500, "GetBlobByPath", err)
- }
- return
- }
- if err = ServeBlob(c, blob); err != nil {
- c.Handle(500, "ServeBlob", err)
- }
-}
diff --git a/routes/repo/editor.go b/routes/repo/editor.go
deleted file mode 100644
index e1beb184..00000000
--- a/routes/repo/editor.go
+++ /dev/null
@@ -1,574 +0,0 @@
-// Copyright 2016 The Gogs Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package repo
-
-import (
- "fmt"
- "io/ioutil"
- "net/http"
- "path"
- "strings"
-
- log "gopkg.in/clog.v1"
-
- "github.com/gogs/git-module"
- "gogs.io/gogs/models"
- "gogs.io/gogs/models/errors"
- "gogs.io/gogs/pkg/context"
- "gogs.io/gogs/pkg/form"
- "gogs.io/gogs/pkg/setting"
- "gogs.io/gogs/pkg/template"
- "gogs.io/gogs/pkg/tool"
-)
-
-const (
- EDIT_FILE = "repo/editor/edit"
- EDIT_DIFF_PREVIEW = "repo/editor/diff_preview"
- DELETE_FILE = "repo/editor/delete"
- UPLOAD_FILE = "repo/editor/upload"
-)
-
-// getParentTreeFields returns list of parent tree names and corresponding tree paths
-// based on given tree path.
-func getParentTreeFields(treePath string) (treeNames []string, treePaths []string) {
- if len(treePath) == 0 {
- return treeNames, treePaths
- }
-
- treeNames = strings.Split(treePath, "/")
- treePaths = make([]string, len(treeNames))
- for i := range treeNames {
- treePaths[i] = strings.Join(treeNames[:i+1], "/")
- }
- return treeNames, treePaths
-}
-
-func editFile(c *context.Context, isNewFile bool) {
- c.PageIs("Edit")
- c.RequireHighlightJS()
- c.RequireSimpleMDE()
- c.Data["IsNewFile"] = isNewFile
-
- treeNames, treePaths := getParentTreeFields(c.Repo.TreePath)
-
- if !isNewFile {
- entry, err := c.Repo.Commit.GetTreeEntryByPath(c.Repo.TreePath)
- if err != nil {
- c.NotFoundOrServerError("GetTreeEntryByPath", git.IsErrNotExist, err)
- return
- }
-
- // No way to edit a directory online.
- if entry.IsDir() {
- c.NotFound()
- return
- }
-
- blob := entry.Blob()
- dataRc, err := blob.Data()
- if err != nil {
- c.ServerError("blob.Data", err)
- return
- }
-
- c.Data["FileSize"] = blob.Size()
- c.Data["FileName"] = blob.Name()
-
- buf := make([]byte, 1024)
- n, _ := dataRc.Read(buf)
- buf = buf[:n]
-
- // Only text file are editable online.
- if !tool.IsTextFile(buf) {
- c.NotFound()
- return
- }
-
- d, _ := ioutil.ReadAll(dataRc)
- buf = append(buf, d...)
- if err, content := template.ToUTF8WithErr(buf); err != nil {
- if err != nil {
- log.Error(2, "Failed to convert encoding to UTF-8: %v", err)
- }
- c.Data["FileContent"] = string(buf)
- } else {
- c.Data["FileContent"] = content
- }
- } else {
- treeNames = append(treeNames, "") // Append empty string to allow user name the new file.
- }
-
- c.Data["ParentTreePath"] = path.Dir(c.Repo.TreePath)
- c.Data["TreeNames"] = treeNames
- c.Data["TreePaths"] = treePaths
- c.Data["BranchLink"] = c.Repo.RepoLink + "/src/" + c.Repo.BranchName
- c.Data["commit_summary"] = ""
- c.Data["commit_message"] = ""
- c.Data["commit_choice"] = "direct"
- c.Data["new_branch_name"] = ""
- c.Data["last_commit"] = c.Repo.Commit.ID
- c.Data["MarkdownFileExts"] = strings.Join(setting.Markdown.FileExtensions, ",")
- c.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
- c.Data["PreviewableFileModes"] = strings.Join(setting.Repository.Editor.PreviewableFileModes, ",")
- c.Data["EditorconfigURLPrefix"] = fmt.Sprintf("%s/api/v1/repos/%s/editorconfig/", setting.AppSubURL, c.Repo.Repository.FullName())
-
- c.Success(EDIT_FILE)
-}
-
-func EditFile(c *context.Context) {
- editFile(c, false)
-}
-
-func NewFile(c *context.Context) {
- editFile(c, true)
-}
-
-func editFilePost(c *context.Context, f form.EditRepoFile, isNewFile bool) {
- c.PageIs("Edit")
- c.RequireHighlightJS()
- c.RequireSimpleMDE()
- c.Data["IsNewFile"] = isNewFile
-
- oldBranchName := c.Repo.BranchName
- branchName := oldBranchName
- oldTreePath := c.Repo.TreePath
- lastCommit := f.LastCommit
- f.LastCommit = c.Repo.Commit.ID.String()
-
- if f.IsNewBrnach() {
- branchName = f.NewBranchName
- }
-
- f.TreePath = strings.Trim(path.Clean("/"+f.TreePath), " /")
- treeNames, treePaths := getParentTreeFields(f.TreePath)
-
- c.Data["ParentTreePath"] = path.Dir(c.Repo.TreePath)
- c.Data["TreePath"] = f.TreePath
- c.Data["TreeNames"] = treeNames
- c.Data["TreePaths"] = treePaths
- c.Data["BranchLink"] = c.Repo.RepoLink + "/src/" + branchName
- c.Data["FileContent"] = f.Content
- c.Data["commit_summary"] = f.CommitSummary
- c.Data["commit_message"] = f.CommitMessage
- c.Data["commit_choice"] = f.CommitChoice
- c.Data["new_branch_name"] = branchName
- c.Data["last_commit"] = f.LastCommit
- c.Data["MarkdownFileExts"] = strings.Join(setting.Markdown.FileExtensions, ",")
- c.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
- c.Data["PreviewableFileModes"] = strings.Join(setting.Repository.Editor.PreviewableFileModes, ",")
-
- if c.HasError() {
- c.Success(EDIT_FILE)
- return
- }
-
- if len(f.TreePath) == 0 {
- c.FormErr("TreePath")
- c.RenderWithErr(c.Tr("repo.editor.filename_cannot_be_empty"), EDIT_FILE, &f)
- return
- }
-
- if oldBranchName != branchName {
- if _, err := c.Repo.Repository.GetBranch(branchName); err == nil {
- c.FormErr("NewBranchName")
- c.RenderWithErr(c.Tr("repo.editor.branch_already_exists", branchName), EDIT_FILE, &f)
- return
- }
- }
-
- var newTreePath string
- for index, part := range treeNames {
- newTreePath = path.Join(newTreePath, part)
- entry, err := c.Repo.Commit.GetTreeEntryByPath(newTreePath)
- if err != nil {
- if git.IsErrNotExist(err) {
- // Means there is no item with that name, so we're good
- break
- }
-
- c.ServerError("Repo.Commit.GetTreeEntryByPath", err)
- return
- }
- if index != len(treeNames)-1 {
- if !entry.IsDir() {
- c.FormErr("TreePath")
- c.RenderWithErr(c.Tr("repo.editor.directory_is_a_file", part), EDIT_FILE, &f)
- return
- }
- } else {
- if entry.IsLink() {
- c.FormErr("TreePath")
- c.RenderWithErr(c.Tr("repo.editor.file_is_a_symlink", part), EDIT_FILE, &f)
- return
- } else if entry.IsDir() {
- c.FormErr("TreePath")
- c.RenderWithErr(c.Tr("repo.editor.filename_is_a_directory", part), EDIT_FILE, &f)
- return
- }
- }
- }
-
- if !isNewFile {
- _, err := c.Repo.Commit.GetTreeEntryByPath(oldTreePath)
- if err != nil {
- if git.IsErrNotExist(err) {
- c.FormErr("TreePath")
- c.RenderWithErr(c.Tr("repo.editor.file_editing_no_longer_exists", oldTreePath), EDIT_FILE, &f)
- } else {
- c.ServerError("GetTreeEntryByPath", err)
- }
- return
- }
- if lastCommit != c.Repo.CommitID {
- files, err := c.Repo.Commit.GetFilesChangedSinceCommit(lastCommit)
- if err != nil {
- c.ServerError("GetFilesChangedSinceCommit", err)
- return
- }
-
- for _, file := range files {
- if file == f.TreePath {
- c.RenderWithErr(c.Tr("repo.editor.file_changed_while_editing", c.Repo.RepoLink+"/compare/"+lastCommit+"..."+c.Repo.CommitID), EDIT_FILE, &f)
- return
- }
- }
- }
- }
-
- if oldTreePath != f.TreePath {
- // We have a new filename (rename or completely new file) so we need to make sure it doesn't already exist, can't clobber.
- entry, err := c.Repo.Commit.GetTreeEntryByPath(f.TreePath)
- if err != nil {
- if !git.IsErrNotExist(err) {
- c.ServerError("GetTreeEntryByPath", err)
- return
- }
- }
- if entry != nil {
- c.FormErr("TreePath")
- c.RenderWithErr(c.Tr("repo.editor.file_already_exists", f.TreePath), EDIT_FILE, &f)
- return
- }
- }
-
- message := strings.TrimSpace(f.CommitSummary)
- if len(message) == 0 {
- if isNewFile {
- message = c.Tr("repo.editor.add", f.TreePath)
- } else {
- message = c.Tr("repo.editor.update", f.TreePath)
- }
- }
-
- f.CommitMessage = strings.TrimSpace(f.CommitMessage)
- if len(f.CommitMessage) > 0 {
- message += "\n\n" + f.CommitMessage
- }
-
- if err := c.Repo.Repository.UpdateRepoFile(c.User, models.UpdateRepoFileOptions{
- LastCommitID: lastCommit,
- OldBranch: oldBranchName,
- NewBranch: branchName,
- OldTreeName: oldTreePath,
- NewTreeName: f.TreePath,
- Message: message,
- Content: strings.Replace(f.Content, "\r", "", -1),
- IsNewFile: isNewFile,
- }); err != nil {
- log.Error(2, "Failed to update repo file: %v", err)
- c.FormErr("TreePath")
- c.RenderWithErr(c.Tr("repo.editor.fail_to_update_file", f.TreePath, errors.InternalServerError), EDIT_FILE, &f)
- return
- }
-
- if f.IsNewBrnach() && c.Repo.PullRequest.Allowed {
- c.Redirect(c.Repo.PullRequestURL(oldBranchName, f.NewBranchName))
- } else {
- c.Redirect(c.Repo.RepoLink + "/src/" + branchName + "/" + f.TreePath)
- }
-}
-
-func EditFilePost(c *context.Context, f form.EditRepoFile) {
- editFilePost(c, f, false)
-}
-
-func NewFilePost(c *context.Context, f form.EditRepoFile) {
- editFilePost(c, f, true)
-}
-
-func DiffPreviewPost(c *context.Context, f form.EditPreviewDiff) {
- treePath := c.Repo.TreePath
-
- entry, err := c.Repo.Commit.GetTreeEntryByPath(treePath)
- if err != nil {
- c.Error(500, "GetTreeEntryByPath: "+err.Error())
- return
- } else if entry.IsDir() {
- c.Error(422)
- return
- }
-
- diff, err := c.Repo.Repository.GetDiffPreview(c.Repo.BranchName, treePath, f.Content)
- if err != nil {
- c.Error(500, "GetDiffPreview: "+err.Error())
- return
- }
-
- if diff.NumFiles() == 0 {
- c.PlainText(200, []byte(c.Tr("repo.editor.no_changes_to_show")))
- return
- }
- c.Data["File"] = diff.Files[0]
-
- c.HTML(200, EDIT_DIFF_PREVIEW)
-}
-
-func DeleteFile(c *context.Context) {
- c.PageIs("Delete")
- c.Data["BranchLink"] = c.Repo.RepoLink + "/src/" + c.Repo.BranchName
- c.Data["TreePath"] = c.Repo.TreePath
- c.Data["commit_summary"] = ""
- c.Data["commit_message"] = ""
- c.Data["commit_choice"] = "direct"
- c.Data["new_branch_name"] = ""
- c.Success(DELETE_FILE)
-}
-
-func DeleteFilePost(c *context.Context, f form.DeleteRepoFile) {
- c.PageIs("Delete")
- c.Data["BranchLink"] = c.Repo.RepoLink + "/src/" + c.Repo.BranchName
- c.Data["TreePath"] = c.Repo.TreePath
-
- oldBranchName := c.Repo.BranchName
- branchName := oldBranchName
-
- if f.IsNewBrnach() {
- branchName = f.NewBranchName
- }
- c.Data["commit_summary"] = f.CommitSummary
- c.Data["commit_message"] = f.CommitMessage
- c.Data["commit_choice"] = f.CommitChoice
- c.Data["new_branch_name"] = branchName
-
- if c.HasError() {
- c.Success(DELETE_FILE)
- return
- }
-
- if oldBranchName != branchName {
- if _, err := c.Repo.Repository.GetBranch(branchName); err == nil {
- c.FormErr("NewBranchName")
- c.RenderWithErr(c.Tr("repo.editor.branch_already_exists", branchName), DELETE_FILE, &f)
- return
- }
- }
-
- message := strings.TrimSpace(f.CommitSummary)
- if len(message) == 0 {
- message = c.Tr("repo.editor.delete", c.Repo.TreePath)
- }
-
- f.CommitMessage = strings.TrimSpace(f.CommitMessage)
- if len(f.CommitMessage) > 0 {
- message += "\n\n" + f.CommitMessage
- }
-
- if err := c.Repo.Repository.DeleteRepoFile(c.User, models.DeleteRepoFileOptions{
- LastCommitID: c.Repo.CommitID,
- OldBranch: oldBranchName,
- NewBranch: branchName,
- TreePath: c.Repo.TreePath,
- Message: message,
- }); err != nil {
- log.Error(2, "Failed to delete repo file: %v", err)
- c.RenderWithErr(c.Tr("repo.editor.fail_to_delete_file", c.Repo.TreePath, errors.InternalServerError), DELETE_FILE, &f)
- return
- }
-
- if f.IsNewBrnach() && c.Repo.PullRequest.Allowed {
- c.Redirect(c.Repo.PullRequestURL(oldBranchName, f.NewBranchName))
- } else {
- c.Flash.Success(c.Tr("repo.editor.file_delete_success", c.Repo.TreePath))
- c.Redirect(c.Repo.RepoLink + "/src/" + branchName)
- }
-}
-
-func renderUploadSettings(c *context.Context) {
- c.RequireDropzone()
- c.Data["UploadAllowedTypes"] = strings.Join(setting.Repository.Upload.AllowedTypes, ",")
- c.Data["UploadMaxSize"] = setting.Repository.Upload.FileMaxSize
- c.Data["UploadMaxFiles"] = setting.Repository.Upload.MaxFiles
-}
-
-func UploadFile(c *context.Context) {
- c.PageIs("Upload")
- renderUploadSettings(c)
-
- treeNames, treePaths := getParentTreeFields(c.Repo.TreePath)
- if len(treeNames) == 0 {
- // We must at least have one element for user to input.
- treeNames = []string{""}
- }
-
- c.Data["TreeNames"] = treeNames
- c.Data["TreePaths"] = treePaths
- c.Data["BranchLink"] = c.Repo.RepoLink + "/src/" + c.Repo.BranchName
- c.Data["commit_summary"] = ""
- c.Data["commit_message"] = ""
- c.Data["commit_choice"] = "direct"
- c.Data["new_branch_name"] = ""
- c.Success(UPLOAD_FILE)
-}
-
-func UploadFilePost(c *context.Context, f form.UploadRepoFile) {
- c.PageIs("Upload")
- renderUploadSettings(c)
-
- oldBranchName := c.Repo.BranchName
- branchName := oldBranchName
-
- if f.IsNewBrnach() {
- branchName = f.NewBranchName
- }
-
- f.TreePath = strings.Trim(path.Clean("/"+f.TreePath), " /")
- treeNames, treePaths := getParentTreeFields(f.TreePath)
- if len(treeNames) == 0 {
- // We must at least have one element for user to input.
- treeNames = []string{""}
- }
-
- c.Data["TreePath"] = f.TreePath
- c.Data["TreeNames"] = treeNames
- c.Data["TreePaths"] = treePaths
- c.Data["BranchLink"] = c.Repo.RepoLink + "/src/" + branchName
- c.Data["commit_summary"] = f.CommitSummary
- c.Data["commit_message"] = f.CommitMessage
- c.Data["commit_choice"] = f.CommitChoice
- c.Data["new_branch_name"] = branchName
-
- if c.HasError() {
- c.Success(UPLOAD_FILE)
- return
- }
-
- if oldBranchName != branchName {
- if _, err := c.Repo.Repository.GetBranch(branchName); err == nil {
- c.FormErr("NewBranchName")
- c.RenderWithErr(c.Tr("repo.editor.branch_already_exists", branchName), UPLOAD_FILE, &f)
- return
- }
- }
-
- var newTreePath string
- for _, part := range treeNames {
- newTreePath = path.Join(newTreePath, part)
- entry, err := c.Repo.Commit.GetTreeEntryByPath(newTreePath)
- if err != nil {
- if git.IsErrNotExist(err) {
- // Means there is no item with that name, so we're good
- break
- }
-
- c.ServerError("GetTreeEntryByPath", err)
- return
- }
-
- // User can only upload files to a directory.
- if !entry.IsDir() {
- c.FormErr("TreePath")
- c.RenderWithErr(c.Tr("repo.editor.directory_is_a_file", part), UPLOAD_FILE, &f)
- return
- }
- }
-
- message := strings.TrimSpace(f.CommitSummary)
- if len(message) == 0 {
- message = c.Tr("repo.editor.upload_files_to_dir", f.TreePath)
- }
-
- f.CommitMessage = strings.TrimSpace(f.CommitMessage)
- if len(f.CommitMessage) > 0 {
- message += "\n\n" + f.CommitMessage
- }
-
- if err := c.Repo.Repository.UploadRepoFiles(c.User, models.UploadRepoFileOptions{
- LastCommitID: c.Repo.CommitID,
- OldBranch: oldBranchName,
- NewBranch: branchName,
- TreePath: f.TreePath,
- Message: message,
- Files: f.Files,
- }); err != nil {
- log.Error(2, "Failed to upload files: %v", err)
- c.FormErr("TreePath")
- c.RenderWithErr(c.Tr("repo.editor.unable_to_upload_files", f.TreePath, errors.InternalServerError), UPLOAD_FILE, &f)
- return
- }
-
- if f.IsNewBrnach() && c.Repo.PullRequest.Allowed {
- c.Redirect(c.Repo.PullRequestURL(oldBranchName, f.NewBranchName))
- } else {
- c.Redirect(c.Repo.RepoLink + "/src/" + branchName + "/" + f.TreePath)
- }
-}
-
-func UploadFileToServer(c *context.Context) {
- file, header, err := c.Req.FormFile("file")
- if err != nil {
- c.Error(http.StatusInternalServerError, fmt.Sprintf("FormFile: %v", err))
- return
- }
- defer file.Close()
-
- buf := make([]byte, 1024)
- n, _ := file.Read(buf)
- if n > 0 {
- buf = buf[:n]
- }
- fileType := http.DetectContentType(buf)
-
- if len(setting.Repository.Upload.AllowedTypes) > 0 {
- allowed := false
- for _, t := range setting.Repository.Upload.AllowedTypes {
- t := strings.Trim(t, " ")
- if t == "*/*" || t == fileType {
- allowed = true
- break
- }
- }
-
- if !allowed {
- c.Error(http.StatusBadRequest, ErrFileTypeForbidden.Error())
- return
- }
- }
-
- upload, err := models.NewUpload(header.Filename, buf, file)
- if err != nil {
- c.Error(http.StatusInternalServerError, fmt.Sprintf("NewUpload: %v", err))
- return
- }
-
- log.Trace("New file uploaded by user[%d]: %s", c.UserID(), upload.UUID)
- c.JSONSuccess(map[string]string{
- "uuid": upload.UUID,
- })
-}
-
-func RemoveUploadFileFromServer(c *context.Context, f form.RemoveUploadFile) {
- if len(f.File) == 0 {
- c.Status(204)
- return
- }
-
- if err := models.DeleteUploadByUUID(f.File); err != nil {
- c.Error(500, fmt.Sprintf("DeleteUploadByUUID: %v", err))
- return
- }
-
- log.Trace("Upload file removed: %s", f.File)
- c.Status(204)
-}
diff --git a/routes/repo/http.go b/routes/repo/http.go
deleted file mode 100644
index 57aa0213..00000000
--- a/routes/repo/http.go
+++ /dev/null
@@ -1,424 +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 repo
-
-import (
- "bytes"
- "compress/gzip"
- "fmt"
- "net/http"
- "os"
- "os/exec"
- "path"
- "regexp"
- "strconv"
- "strings"
- "time"
-
- log "gopkg.in/clog.v1"
- "gopkg.in/macaron.v1"
-
- "gogs.io/gogs/models"
- "gogs.io/gogs/models/errors"
- "gogs.io/gogs/pkg/context"
- "gogs.io/gogs/pkg/setting"
- "gogs.io/gogs/pkg/tool"
-)
-
-type HTTPContext struct {
- *context.Context
- OwnerName string
- OwnerSalt string
- RepoID int64
- RepoName string
- AuthUser *models.User
-}
-
-// 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)
-}
-
-func HTTPContexter() macaron.Handler {
- return func(c *context.Context) {
- if len(setting.HTTP.AccessControlAllowOrigin) > 0 {
- // Set CORS headers for browser-based git clients
- c.Resp.Header().Set("Access-Control-Allow-Origin", setting.HTTP.AccessControlAllowOrigin)
- c.Resp.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization, User-Agent")
-
- // Handle preflight OPTIONS request
- if c.Req.Method == "OPTIONS" {
- c.Status(http.StatusOK)
- return
- }
- }
-
- ownerName := c.Params(":username")
- repoName := strings.TrimSuffix(c.Params(":reponame"), ".git")
- repoName = strings.TrimSuffix(repoName, ".wiki")
-
- isPull := c.Query("service") == "git-upload-pack" ||
- strings.HasSuffix(c.Req.URL.Path, "git-upload-pack") ||
- c.Req.Method == "GET"
-
- owner, err := models.GetUserByName(ownerName)
- if err != nil {
- c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
- return
- }
-
- repo, err := models.GetRepositoryByName(owner.ID, repoName)
- if err != nil {
- c.NotFoundOrServerError("GetRepositoryByName", errors.IsRepoNotExist, err)
- return
- }
-
- // Authentication is not required for pulling from public repositories.
- if isPull && !repo.IsPrivate && !setting.Service.RequireSignInView {
- c.Map(&HTTPContext{
- Context: c,
- })
- return
- }
-
- // In case user requested a wrong URL and not intended to access Git objects.
- action := c.Params("*")
- if !strings.Contains(action, "git-") &&
- !strings.Contains(action, "info/") &&
- !strings.Contains(action, "HEAD") &&
- !strings.Contains(action, "objects/") {
- c.NotFound()
- return
- }
-
- // Handle HTTP Basic Authentication
- authHead := c.Req.Header.Get("Authorization")
- if len(authHead) == 0 {
- askCredentials(c, http.StatusUnauthorized, "")
- return
- }
-
- auths := strings.Fields(authHead)
- if len(auths) != 2 || auths[0] != "Basic" {
- askCredentials(c, http.StatusUnauthorized, "")
- return
- }
- authUsername, authPassword, err := tool.BasicAuthDecode(auths[1])
- if err != nil {
- askCredentials(c, http.StatusUnauthorized, "")
- return
- }
-
- authUser, err := models.UserLogin(authUsername, authPassword, -1)
- if err != nil && !errors.IsUserNotExist(err) {
- c.Handle(http.StatusInternalServerError, "UserLogin", err)
- return
- }
-
- // If username and password combination failed, try again using username as a token.
- if authUser == nil {
- token, err := models.GetAccessTokenBySHA(authUsername)
- if err != nil {
- if models.IsErrAccessTokenEmpty(err) || models.IsErrAccessTokenNotExist(err) {
- askCredentials(c, http.StatusUnauthorized, "")
- } else {
- c.Handle(http.StatusInternalServerError, "GetAccessTokenBySHA", err)
- }
- return
- }
- token.Updated = time.Now()
- // TODO: verify or update token.Updated in database
-
- authUser, err = models.GetUserByID(token.UID)
- 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)
- return
- }
- } else if authUser.IsEnabledTwoFactor() {
- askCredentials(c, http.StatusUnauthorized, `User with two-factor authentication enabled cannot perform HTTP/HTTPS operations via plain username and password
-Please create and use personal access token on user settings page`)
- return
- }
-
- log.Trace("HTTPGit - Authenticated user: %s", authUser.Name)
-
- mode := models.ACCESS_MODE_WRITE
- if isPull {
- mode = models.ACCESS_MODE_READ
- }
- has, err := models.HasAccess(authUser.ID, repo, mode)
- if err != nil {
- c.Handle(http.StatusInternalServerError, "HasAccess", err)
- return
- } else if !has {
- askCredentials(c, http.StatusForbidden, "User permission denied")
- return
- }
-
- if !isPull && repo.IsMirror {
- c.HandleText(http.StatusForbidden, "Mirror repository is read-only")
- return
- }
-
- c.Map(&HTTPContext{
- Context: c,
- OwnerName: ownerName,
- OwnerSalt: owner.Salt,
- RepoID: repo.ID,
- RepoName: repoName,
- AuthUser: authUser,
- })
- }
-}
-
-type serviceHandler struct {
- w http.ResponseWriter
- r *http.Request
- dir string
- file string
-
- authUser *models.User
- ownerName string
- ownerSalt string
- repoID int64
- repoName string
-}
-
-func (h *serviceHandler) setHeaderNoCache() {
- h.w.Header().Set("Expires", "Fri, 01 Jan 1980 00:00:00 GMT")
- h.w.Header().Set("Pragma", "no-cache")
- h.w.Header().Set("Cache-Control", "no-cache, max-age=0, must-revalidate")
-}
-
-func (h *serviceHandler) setHeaderCacheForever() {
- now := time.Now().Unix()
- expires := now + 31536000
- h.w.Header().Set("Date", fmt.Sprintf("%d", now))
- h.w.Header().Set("Expires", fmt.Sprintf("%d", expires))
- h.w.Header().Set("Cache-Control", "public, max-age=31536000")
-}
-
-func (h *serviceHandler) sendFile(contentType string) {
- reqFile := path.Join(h.dir, h.file)
- fi, err := os.Stat(reqFile)
- if os.IsNotExist(err) {
- h.w.WriteHeader(http.StatusNotFound)
- return
- }
-
- h.w.Header().Set("Content-Type", contentType)
- h.w.Header().Set("Content-Length", fmt.Sprintf("%d", fi.Size()))
- h.w.Header().Set("Last-Modified", fi.ModTime().Format(http.TimeFormat))
- http.ServeFile(h.w, h.r, reqFile)
-}
-
-func serviceRPC(h serviceHandler, service string) {
- defer h.r.Body.Close()
-
- if h.r.Header.Get("Content-Type") != fmt.Sprintf("application/x-git-%s-request", service) {
- h.w.WriteHeader(http.StatusUnauthorized)
- return
- }
- h.w.Header().Set("Content-Type", fmt.Sprintf("application/x-git-%s-result", service))
-
- var (
- reqBody = h.r.Body
- err error
- )
-
- // Handle GZIP
- if h.r.Header.Get("Content-Encoding") == "gzip" {
- reqBody, err = gzip.NewReader(reqBody)
- if err != nil {
- log.Error(2, "HTTP.Get: fail to create gzip reader: %v", err)
- h.w.WriteHeader(http.StatusInternalServerError)
- return
- }
- }
-
- var stderr bytes.Buffer
- cmd := exec.Command("git", service, "--stateless-rpc", h.dir)
- if service == "receive-pack" {
- cmd.Env = append(os.Environ(), models.ComposeHookEnvs(models.ComposeHookEnvsOptions{
- AuthUser: h.authUser,
- OwnerName: h.ownerName,
- OwnerSalt: h.ownerSalt,
- RepoID: h.repoID,
- RepoName: h.repoName,
- RepoPath: h.dir,
- })...)
- }
- cmd.Dir = h.dir
- cmd.Stdout = h.w
- cmd.Stderr = &stderr
- cmd.Stdin = reqBody
- if err = cmd.Run(); err != nil {
- log.Error(2, "HTTP.serviceRPC: fail to serve RPC '%s': %v - %s", service, err, stderr.String())
- h.w.WriteHeader(http.StatusInternalServerError)
- return
- }
-}
-
-func serviceUploadPack(h serviceHandler) {
- serviceRPC(h, "upload-pack")
-}
-
-func serviceReceivePack(h serviceHandler) {
- serviceRPC(h, "receive-pack")
-}
-
-func getServiceType(r *http.Request) string {
- serviceType := r.FormValue("service")
- if !strings.HasPrefix(serviceType, "git-") {
- return ""
- }
- return strings.TrimPrefix(serviceType, "git-")
-}
-
-// FIXME: use process module
-func gitCommand(dir string, args ...string) []byte {
- cmd := exec.Command("git", args...)
- cmd.Dir = dir
- out, err := cmd.Output()
- if err != nil {
- log.Error(2, fmt.Sprintf("Git: %v - %s", err, out))
- }
- return out
-}
-
-func updateServerInfo(dir string) []byte {
- return gitCommand(dir, "update-server-info")
-}
-
-func packetWrite(str string) []byte {
- s := strconv.FormatInt(int64(len(str)+4), 16)
- if len(s)%4 != 0 {
- s = strings.Repeat("0", 4-len(s)%4) + s
- }
- return []byte(s + str)
-}
-
-func getInfoRefs(h serviceHandler) {
- h.setHeaderNoCache()
- service := getServiceType(h.r)
- if service != "upload-pack" && service != "receive-pack" {
- updateServerInfo(h.dir)
- h.sendFile("text/plain; charset=utf-8")
- return
- }
-
- refs := gitCommand(h.dir, service, "--stateless-rpc", "--advertise-refs", ".")
- h.w.Header().Set("Content-Type", fmt.Sprintf("application/x-git-%s-advertisement", service))
- h.w.WriteHeader(http.StatusOK)
- h.w.Write(packetWrite("# service=git-" + service + "\n"))
- h.w.Write([]byte("0000"))
- h.w.Write(refs)
-}
-
-func getTextFile(h serviceHandler) {
- h.setHeaderNoCache()
- h.sendFile("text/plain")
-}
-
-func getInfoPacks(h serviceHandler) {
- h.setHeaderCacheForever()
- h.sendFile("text/plain; charset=utf-8")
-}
-
-func getLooseObject(h serviceHandler) {
- h.setHeaderCacheForever()
- h.sendFile("application/x-git-loose-object")
-}
-
-func getPackFile(h serviceHandler) {
- h.setHeaderCacheForever()
- h.sendFile("application/x-git-packed-objects")
-}
-
-func getIdxFile(h serviceHandler) {
- h.setHeaderCacheForever()
- h.sendFile("application/x-git-packed-objects-toc")
-}
-
-var routes = []struct {
- reg *regexp.Regexp
- method string
- handler func(serviceHandler)
-}{
- {regexp.MustCompile("(.*?)/git-upload-pack$"), "POST", serviceUploadPack},
- {regexp.MustCompile("(.*?)/git-receive-pack$"), "POST", serviceReceivePack},
- {regexp.MustCompile("(.*?)/info/refs$"), "GET", getInfoRefs},
- {regexp.MustCompile("(.*?)/HEAD$"), "GET", getTextFile},
- {regexp.MustCompile("(.*?)/objects/info/alternates$"), "GET", getTextFile},
- {regexp.MustCompile("(.*?)/objects/info/http-alternates$"), "GET", getTextFile},
- {regexp.MustCompile("(.*?)/objects/info/packs$"), "GET", getInfoPacks},
- {regexp.MustCompile("(.*?)/objects/info/[^/]*$"), "GET", getTextFile},
- {regexp.MustCompile("(.*?)/objects/[0-9a-f]{2}/[0-9a-f]{38}$"), "GET", getLooseObject},
- {regexp.MustCompile("(.*?)/objects/pack/pack-[0-9a-f]{40}\\.pack$"), "GET", getPackFile},
- {regexp.MustCompile("(.*?)/objects/pack/pack-[0-9a-f]{40}\\.idx$"), "GET", getIdxFile},
-}
-
-func getGitRepoPath(dir string) (string, error) {
- if !strings.HasSuffix(dir, ".git") {
- dir += ".git"
- }
-
- filename := path.Join(setting.RepoRootPath, dir)
- if _, err := os.Stat(filename); os.IsNotExist(err) {
- return "", err
- }
-
- return filename, nil
-}
-
-func HTTP(c *HTTPContext) {
- for _, route := range routes {
- reqPath := strings.ToLower(c.Req.URL.Path)
- m := route.reg.FindStringSubmatch(reqPath)
- if m == nil {
- continue
- }
-
- // We perform check here because routes matched in cmd/web.go is wider than needed,
- // but we only want to output this message only if user is really trying to access
- // Git HTTP endpoints.
- if setting.Repository.DisableHTTPGit {
- c.HandleText(http.StatusForbidden, "Interacting with repositories by HTTP protocol is not disabled")
- return
- }
-
- if route.method != c.Req.Method {
- c.NotFound()
- return
- }
-
- file := strings.TrimPrefix(reqPath, m[1]+"/")
- dir, err := getGitRepoPath(m[1])
- if err != nil {
- log.Warn("HTTP.getGitRepoPath: %v", err)
- c.NotFound()
- return
- }
-
- route.handler(serviceHandler{
- w: c.Resp,
- r: c.Req.Request,
- dir: dir,
- file: file,
-
- authUser: c.AuthUser,
- ownerName: c.OwnerName,
- ownerSalt: c.OwnerSalt,
- repoID: c.RepoID,
- repoName: c.RepoName,
- })
- return
- }
-
- c.NotFound()
-}
diff --git a/routes/repo/issue.go b/routes/repo/issue.go
deleted file mode 100644
index a9d739c5..00000000
--- a/routes/repo/issue.go
+++ /dev/null
@@ -1,1278 +0,0 @@
-// Copyright 2014 The Gogs Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package repo
-
-import (
- "fmt"
- "io"
- "io/ioutil"
- "net/http"
- "net/url"
- "strings"
- "time"
-
- "github.com/unknwon/com"
- "github.com/unknwon/paginater"
- log "gopkg.in/clog.v1"
-
- "gogs.io/gogs/models"
- "gogs.io/gogs/models/errors"
- "gogs.io/gogs/pkg/context"
- "gogs.io/gogs/pkg/form"
- "gogs.io/gogs/pkg/markup"
- "gogs.io/gogs/pkg/setting"
- "gogs.io/gogs/pkg/template"
- "gogs.io/gogs/pkg/tool"
-)
-
-const (
- ISSUES = "repo/issue/list"
- ISSUE_NEW = "repo/issue/new"
- ISSUE_VIEW = "repo/issue/view"
-
- LABELS = "repo/issue/labels"
-
- MILESTONE = "repo/issue/milestones"
- MILESTONE_NEW = "repo/issue/milestone_new"
- MILESTONE_EDIT = "repo/issue/milestone_edit"
-
- ISSUE_TEMPLATE_KEY = "IssueTemplate"
-)
-
-var (
- ErrFileTypeForbidden = errors.New("File type is not allowed")
- ErrTooManyFiles = errors.New("Maximum number of files to upload exceeded")
-
- IssueTemplateCandidates = []string{
- "ISSUE_TEMPLATE.md",
- ".gogs/ISSUE_TEMPLATE.md",
- ".github/ISSUE_TEMPLATE.md",
- }
-)
-
-func MustEnableIssues(c *context.Context) {
- if !c.Repo.Repository.EnableIssues {
- c.Handle(404, "MustEnableIssues", nil)
- return
- }
-
- if c.Repo.Repository.EnableExternalTracker {
- c.Redirect(c.Repo.Repository.ExternalTrackerURL)
- return
- }
-}
-
-func MustAllowPulls(c *context.Context) {
- if !c.Repo.Repository.AllowsPulls() {
- c.Handle(404, "MustAllowPulls", nil)
- return
- }
-
- // User can send pull request if owns a forked repository.
- if c.IsLogged && c.User.HasForkedRepo(c.Repo.Repository.ID) {
- c.Repo.PullRequest.Allowed = true
- c.Repo.PullRequest.HeadInfo = c.User.Name + ":" + c.Repo.BranchName
- }
-}
-
-func RetrieveLabels(c *context.Context) {
- labels, err := models.GetLabelsByRepoID(c.Repo.Repository.ID)
- if err != nil {
- c.Handle(500, "RetrieveLabels.GetLabels", err)
- return
- }
- for _, l := range labels {
- l.CalOpenIssues()
- }
- c.Data["Labels"] = labels
- c.Data["NumLabels"] = len(labels)
-}
-
-func issues(c *context.Context, isPullList bool) {
- if isPullList {
- MustAllowPulls(c)
- if c.Written() {
- return
- }
- c.Data["Title"] = c.Tr("repo.pulls")
- c.Data["PageIsPullList"] = true
-
- } else {
- MustEnableIssues(c)
- if c.Written() {
- return
- }
- c.Data["Title"] = c.Tr("repo.issues")
- c.Data["PageIsIssueList"] = true
- }
-
- viewType := c.Query("type")
- sortType := c.Query("sort")
- types := []string{"assigned", "created_by", "mentioned"}
- if !com.IsSliceContainsStr(types, viewType) {
- viewType = "all"
- }
-
- // Must sign in to see issues about you.
- if viewType != "all" && !c.IsLogged {
- c.SetCookie("redirect_to", "/"+url.QueryEscape(setting.AppSubURL+c.Req.RequestURI), 0, setting.AppSubURL)
- c.Redirect(setting.AppSubURL + "/user/login")
- return
- }
-
- var (
- assigneeID = c.QueryInt64("assignee")
- posterID int64
- )
- filterMode := models.FILTER_MODE_YOUR_REPOS
- switch viewType {
- case "assigned":
- filterMode = models.FILTER_MODE_ASSIGN
- assigneeID = c.User.ID
- case "created_by":
- filterMode = models.FILTER_MODE_CREATE
- posterID = c.User.ID
- case "mentioned":
- filterMode = models.FILTER_MODE_MENTION
- }
-
- var uid int64 = -1
- if c.IsLogged {
- uid = c.User.ID
- }
-
- repo := c.Repo.Repository
- selectLabels := c.Query("labels")
- milestoneID := c.QueryInt64("milestone")
- isShowClosed := c.Query("state") == "closed"
- issueStats := models.GetIssueStats(&models.IssueStatsOptions{
- RepoID: repo.ID,
- UserID: uid,
- Labels: selectLabels,
- MilestoneID: milestoneID,
- AssigneeID: assigneeID,
- FilterMode: filterMode,
- IsPull: isPullList,
- })
-
- page := c.QueryInt("page")
- if page <= 1 {
- page = 1
- }
-
- var total int
- if !isShowClosed {
- total = int(issueStats.OpenCount)
- } else {
- total = int(issueStats.ClosedCount)
- }
- pager := paginater.New(total, setting.UI.IssuePagingNum, page, 5)
- c.Data["Page"] = pager
-
- issues, err := models.Issues(&models.IssuesOptions{
- UserID: uid,
- AssigneeID: assigneeID,
- RepoID: repo.ID,
- PosterID: posterID,
- MilestoneID: milestoneID,
- Page: pager.Current(),
- IsClosed: isShowClosed,
- IsMention: filterMode == models.FILTER_MODE_MENTION,
- IsPull: isPullList,
- Labels: selectLabels,
- SortType: sortType,
- })
- if err != nil {
- c.Handle(500, "Issues", err)
- return
- }
-
- // Get issue-user relations.
- pairs, err := models.GetIssueUsers(repo.ID, posterID, isShowClosed)
- if err != nil {
- c.Handle(500, "GetIssueUsers", err)
- return
- }
-
- // Get posters.
- for i := range issues {
- if !c.IsLogged {
- issues[i].IsRead = true
- continue
- }
-
- // Check read status.
- idx := models.PairsContains(pairs, issues[i].ID, c.User.ID)
- if idx > -1 {
- issues[i].IsRead = pairs[idx].IsRead
- } else {
- issues[i].IsRead = true
- }
- }
- c.Data["Issues"] = issues
-
- // Get milestones.
- c.Data["Milestones"], err = models.GetMilestonesByRepoID(repo.ID)
- if err != nil {
- c.Handle(500, "GetAllRepoMilestones", err)
- return
- }
-
- // Get assignees.
- c.Data["Assignees"], err = repo.GetAssignees()
- if err != nil {
- c.Handle(500, "GetAssignees", err)
- return
- }
-
- if viewType == "assigned" {
- assigneeID = 0 // Reset ID to prevent unexpected selection of assignee.
- }
-
- c.Data["IssueStats"] = issueStats
- c.Data["SelectLabels"] = com.StrTo(selectLabels).MustInt64()
- c.Data["ViewType"] = viewType
- c.Data["SortType"] = sortType
- c.Data["MilestoneID"] = milestoneID
- c.Data["AssigneeID"] = assigneeID
- c.Data["IsShowClosed"] = isShowClosed
- if isShowClosed {
- c.Data["State"] = "closed"
- } else {
- c.Data["State"] = "open"
- }
-
- c.HTML(200, ISSUES)
-}
-
-func Issues(c *context.Context) {
- issues(c, false)
-}
-
-func Pulls(c *context.Context) {
- issues(c, true)
-}
-
-func renderAttachmentSettings(c *context.Context) {
- c.Data["RequireDropzone"] = true
- c.Data["IsAttachmentEnabled"] = setting.AttachmentEnabled
- c.Data["AttachmentAllowedTypes"] = setting.AttachmentAllowedTypes
- c.Data["AttachmentMaxSize"] = setting.AttachmentMaxSize
- c.Data["AttachmentMaxFiles"] = setting.AttachmentMaxFiles
-}
-
-func RetrieveRepoMilestonesAndAssignees(c *context.Context, repo *models.Repository) {
- var err error
- c.Data["OpenMilestones"], err = models.GetMilestones(repo.ID, -1, false)
- if err != nil {
- c.Handle(500, "GetMilestones", err)
- return
- }
- c.Data["ClosedMilestones"], err = models.GetMilestones(repo.ID, -1, true)
- if err != nil {
- c.Handle(500, "GetMilestones", err)
- return
- }
-
- c.Data["Assignees"], err = repo.GetAssignees()
- if err != nil {
- c.Handle(500, "GetAssignees", err)
- return
- }
-}
-
-func RetrieveRepoMetas(c *context.Context, repo *models.Repository) []*models.Label {
- if !c.Repo.IsWriter() {
- return nil
- }
-
- labels, err := models.GetLabelsByRepoID(repo.ID)
- if err != nil {
- c.Handle(500, "GetLabelsByRepoID", err)
- return nil
- }
- c.Data["Labels"] = labels
-
- RetrieveRepoMilestonesAndAssignees(c, repo)
- if c.Written() {
- return nil
- }
-
- return labels
-}
-
-func getFileContentFromDefaultBranch(c *context.Context, filename string) (string, bool) {
- var r io.Reader
- var bytes []byte
-
- if c.Repo.Commit == nil {
- var err error
- c.Repo.Commit, err = c.Repo.GitRepo.GetBranchCommit(c.Repo.Repository.DefaultBranch)
- if err != nil {
- return "", false
- }
- }
-
- entry, err := c.Repo.Commit.GetTreeEntryByPath(filename)
- if err != nil {
- return "", false
- }
- r, err = entry.Blob().Data()
- if err != nil {
- return "", false
- }
- bytes, err = ioutil.ReadAll(r)
- if err != nil {
- return "", false
- }
- return string(bytes), true
-}
-
-func setTemplateIfExists(c *context.Context, ctxDataKey string, possibleFiles []string) {
- for _, filename := range possibleFiles {
- content, found := getFileContentFromDefaultBranch(c, filename)
- if found {
- c.Data[ctxDataKey] = content
- return
- }
- }
-}
-
-func NewIssue(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.issues.new")
- c.Data["PageIsIssueList"] = true
- c.Data["RequireHighlightJS"] = true
- c.Data["RequireSimpleMDE"] = true
- c.Data["title"] = c.Query("title")
- c.Data["content"] = c.Query("content")
- setTemplateIfExists(c, ISSUE_TEMPLATE_KEY, IssueTemplateCandidates)
- renderAttachmentSettings(c)
-
- RetrieveRepoMetas(c, c.Repo.Repository)
- if c.Written() {
- return
- }
-
- c.HTML(200, ISSUE_NEW)
-}
-
-func ValidateRepoMetas(c *context.Context, f form.NewIssue) ([]int64, int64, int64) {
- var (
- repo = c.Repo.Repository
- err error
- )
-
- labels := RetrieveRepoMetas(c, c.Repo.Repository)
- if c.Written() {
- return nil, 0, 0
- }
-
- if !c.Repo.IsWriter() {
- return nil, 0, 0
- }
-
- // Check labels.
- labelIDs := tool.StringsToInt64s(strings.Split(f.LabelIDs, ","))
- labelIDMark := tool.Int64sToMap(labelIDs)
- hasSelected := false
- for i := range labels {
- if labelIDMark[labels[i].ID] {
- labels[i].IsChecked = true
- hasSelected = true
- }
- }
- c.Data["HasSelectedLabel"] = hasSelected
- c.Data["label_ids"] = f.LabelIDs
- c.Data["Labels"] = labels
-
- // Check milestone.
- milestoneID := f.MilestoneID
- if milestoneID > 0 {
- c.Data["Milestone"], err = repo.GetMilestoneByID(milestoneID)
- if err != nil {
- c.Handle(500, "GetMilestoneByID", err)
- return nil, 0, 0
- }
- c.Data["milestone_id"] = milestoneID
- }
-
- // Check assignee.
- assigneeID := f.AssigneeID
- if assigneeID > 0 {
- c.Data["Assignee"], err = repo.GetAssigneeByID(assigneeID)
- if err != nil {
- c.Handle(500, "GetAssigneeByID", err)
- return nil, 0, 0
- }
- c.Data["assignee_id"] = assigneeID
- }
-
- return labelIDs, milestoneID, assigneeID
-}
-
-func NewIssuePost(c *context.Context, f form.NewIssue) {
- c.Data["Title"] = c.Tr("repo.issues.new")
- c.Data["PageIsIssueList"] = true
- c.Data["RequireHighlightJS"] = true
- c.Data["RequireSimpleMDE"] = true
- renderAttachmentSettings(c)
-
- labelIDs, milestoneID, assigneeID := ValidateRepoMetas(c, f)
- if c.Written() {
- return
- }
-
- if c.HasError() {
- c.HTML(200, ISSUE_NEW)
- return
- }
-
- var attachments []string
- if setting.AttachmentEnabled {
- attachments = f.Files
- }
-
- issue := &models.Issue{
- RepoID: c.Repo.Repository.ID,
- Title: f.Title,
- PosterID: c.User.ID,
- Poster: c.User,
- MilestoneID: milestoneID,
- AssigneeID: assigneeID,
- Content: f.Content,
- }
- if err := models.NewIssue(c.Repo.Repository, issue, labelIDs, attachments); err != nil {
- c.Handle(500, "NewIssue", err)
- return
- }
-
- log.Trace("Issue created: %d/%d", c.Repo.Repository.ID, issue.ID)
- c.Redirect(c.Repo.RepoLink + "/issues/" + com.ToStr(issue.Index))
-}
-
-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))
- return
- }
- defer file.Close()
-
- buf := make([]byte, 1024)
- n, _ := file.Read(buf)
- if n > 0 {
- buf = buf[:n]
- }
- fileType := http.DetectContentType(buf)
-
- allowed := false
- for _, t := range allowedTypes {
- t := strings.Trim(t, " ")
- if t == "*/*" || t == fileType {
- allowed = true
- break
- }
- }
-
- if !allowed {
- c.Error(400, ErrFileTypeForbidden.Error())
- return
- }
-
- attach, err := models.NewAttachment(header.Filename, buf, file)
- if err != nil {
- c.Error(500, fmt.Sprintf("NewAttachment: %v", err))
- return
- }
-
- log.Trace("New attachment uploaded: %s", attach.UUID)
- c.JSON(200, map[string]string{
- "uuid": attach.UUID,
- })
-}
-
-func UploadIssueAttachment(c *context.Context) {
- if !setting.AttachmentEnabled {
- c.NotFound()
- return
- }
-
- uploadAttachment(c, strings.Split(setting.AttachmentAllowedTypes, ","))
-}
-
-func viewIssue(c *context.Context, isPullList bool) {
- c.Data["RequireHighlightJS"] = true
- c.Data["RequireDropzone"] = true
- renderAttachmentSettings(c)
-
- index := c.ParamsInt64(":index")
- if index <= 0 {
- c.NotFound()
- return
- }
-
- issue, err := models.GetIssueByIndex(c.Repo.Repository.ID, index)
- if err != nil {
- c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
- return
- }
- c.Data["Title"] = issue.Title
-
- // Make sure type and URL matches.
- if !isPullList && issue.IsPull {
- c.Redirect(c.Repo.RepoLink + "/pulls/" + com.ToStr(issue.Index))
- return
- } else if isPullList && !issue.IsPull {
- c.Redirect(c.Repo.RepoLink + "/issues/" + com.ToStr(issue.Index))
- return
- }
-
- if issue.IsPull {
- MustAllowPulls(c)
- if c.Written() {
- return
- }
- c.Data["PageIsPullList"] = true
- c.Data["PageIsPullConversation"] = true
- } else {
- MustEnableIssues(c)
- if c.Written() {
- return
- }
- c.Data["PageIsIssueList"] = true
- }
-
- issue.RenderedContent = string(markup.Markdown(issue.Content, c.Repo.RepoLink, c.Repo.Repository.ComposeMetas()))
-
- repo := c.Repo.Repository
-
- // Get more information if it's a pull request.
- if issue.IsPull {
- if issue.PullRequest.HasMerged {
- c.Data["DisableStatusChange"] = issue.PullRequest.HasMerged
- PrepareMergedViewPullInfo(c, issue)
- } else {
- PrepareViewPullInfo(c, issue)
- }
- if c.Written() {
- return
- }
- }
-
- // Metas.
- // Check labels.
- labelIDMark := make(map[int64]bool)
- for i := range issue.Labels {
- labelIDMark[issue.Labels[i].ID] = true
- }
- labels, err := models.GetLabelsByRepoID(repo.ID)
- if err != nil {
- c.Handle(500, "GetLabelsByRepoID", err)
- return
- }
- hasSelected := false
- for i := range labels {
- if labelIDMark[labels[i].ID] {
- labels[i].IsChecked = true
- hasSelected = true
- }
- }
- c.Data["HasSelectedLabel"] = hasSelected
- c.Data["Labels"] = labels
-
- // Check milestone and assignee.
- if c.Repo.IsWriter() {
- RetrieveRepoMilestonesAndAssignees(c, repo)
- if c.Written() {
- return
- }
- }
-
- if c.IsLogged {
- // Update issue-user.
- if err = issue.ReadBy(c.User.ID); err != nil {
- c.Handle(500, "ReadBy", err)
- return
- }
- }
-
- var (
- tag models.CommentTag
- ok bool
- marked = make(map[int64]models.CommentTag)
- comment *models.Comment
- participants = make([]*models.User, 1, 10)
- )
-
- // Render comments and and fetch participants.
- participants[0] = issue.Poster
- for _, comment = range issue.Comments {
- if comment.Type == models.COMMENT_TYPE_COMMENT {
- comment.RenderedContent = string(markup.Markdown(comment.Content, c.Repo.RepoLink, c.Repo.Repository.ComposeMetas()))
-
- // Check tag.
- tag, ok = marked[comment.PosterID]
- if ok {
- comment.ShowTag = tag
- continue
- }
-
- if repo.IsOwnedBy(comment.PosterID) ||
- (repo.Owner.IsOrganization() && repo.Owner.IsOwnedBy(comment.PosterID)) {
- comment.ShowTag = models.COMMENT_TAG_OWNER
- } else if comment.Poster.IsWriterOfRepo(repo) {
- comment.ShowTag = models.COMMENT_TAG_WRITER
- } else if comment.PosterID == issue.PosterID {
- comment.ShowTag = models.COMMENT_TAG_POSTER
- }
-
- marked[comment.PosterID] = comment.ShowTag
-
- isAdded := false
- for j := range participants {
- if comment.Poster == participants[j] {
- isAdded = true
- break
- }
- }
- if !isAdded && !issue.IsPoster(comment.Poster.ID) {
- participants = append(participants, comment.Poster)
- }
- }
- }
-
- if issue.IsPull && issue.PullRequest.HasMerged {
- pull := issue.PullRequest
- branchProtected := false
- protectBranch, err := models.GetProtectBranchOfRepoByName(pull.BaseRepoID, pull.HeadBranch)
- if err != nil {
- if !errors.IsErrBranchNotExist(err) {
- c.ServerError("GetProtectBranchOfRepoByName", err)
- return
- }
- } else {
- branchProtected = protectBranch.Protected
- }
-
- c.Data["IsPullBranchDeletable"] = pull.BaseRepoID == pull.HeadRepoID &&
- c.Repo.IsWriter() && c.Repo.GitRepo.IsBranchExist(pull.HeadBranch) &&
- !branchProtected
-
- deleteBranchUrl := template.EscapePound(c.Repo.RepoLink + "/branches/delete/" + pull.HeadBranch)
- c.Data["DeleteBranchLink"] = fmt.Sprintf("%s?commit=%s&redirect_to=%s", deleteBranchUrl, pull.MergedCommitID, c.Data["Link"])
- }
-
- c.Data["Participants"] = participants
- c.Data["NumParticipants"] = len(participants)
- c.Data["Issue"] = issue
- c.Data["IsIssueOwner"] = c.Repo.IsWriter() || (c.IsLogged && issue.IsPoster(c.User.ID))
- c.Data["SignInLink"] = setting.AppSubURL + "/user/login?redirect_to=" + c.Data["Link"].(string)
- c.HTML(200, ISSUE_VIEW)
-}
-
-func ViewIssue(c *context.Context) {
- viewIssue(c, false)
-}
-
-func ViewPull(c *context.Context) {
- viewIssue(c, true)
-}
-
-func getActionIssue(c *context.Context) *models.Issue {
- issue, err := models.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
- if err != nil {
- c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
- return nil
- }
-
- // Prevent guests accessing pull requests
- if !c.Repo.HasAccess() && issue.IsPull {
- c.NotFound()
- return nil
- }
-
- return issue
-}
-
-func UpdateIssueTitle(c *context.Context) {
- issue := getActionIssue(c)
- if c.Written() {
- return
- }
-
- if !c.IsLogged || (!issue.IsPoster(c.User.ID) && !c.Repo.IsWriter()) {
- c.Error(403)
- return
- }
-
- title := c.QueryTrim("title")
- if len(title) == 0 {
- c.Error(204)
- return
- }
-
- if err := issue.ChangeTitle(c.User, title); err != nil {
- c.Handle(500, "ChangeTitle", err)
- return
- }
-
- c.JSON(200, map[string]interface{}{
- "title": issue.Title,
- })
-}
-
-func UpdateIssueContent(c *context.Context) {
- issue := getActionIssue(c)
- if c.Written() {
- return
- }
-
- if !c.IsLogged || (c.User.ID != issue.PosterID && !c.Repo.IsWriter()) {
- c.Error(403)
- return
- }
-
- content := c.Query("content")
- if err := issue.ChangeContent(c.User, content); err != nil {
- c.Handle(500, "ChangeContent", err)
- return
- }
-
- c.JSON(200, map[string]string{
- "content": string(markup.Markdown(issue.Content, c.Query("context"), c.Repo.Repository.ComposeMetas())),
- })
-}
-
-func UpdateIssueLabel(c *context.Context) {
- issue := getActionIssue(c)
- if c.Written() {
- return
- }
-
- if c.Query("action") == "clear" {
- if err := issue.ClearLabels(c.User); err != nil {
- c.Handle(500, "ClearLabels", err)
- return
- }
- } else {
- isAttach := c.Query("action") == "attach"
- label, err := models.GetLabelOfRepoByID(c.Repo.Repository.ID, c.QueryInt64("id"))
- if err != nil {
- if models.IsErrLabelNotExist(err) {
- c.Error(404, "GetLabelByID")
- } else {
- c.Handle(500, "GetLabelByID", err)
- }
- return
- }
-
- if isAttach && !issue.HasLabel(label.ID) {
- if err = issue.AddLabel(c.User, label); err != nil {
- c.Handle(500, "AddLabel", err)
- return
- }
- } else if !isAttach && issue.HasLabel(label.ID) {
- if err = issue.RemoveLabel(c.User, label); err != nil {
- c.Handle(500, "RemoveLabel", err)
- return
- }
- }
- }
-
- c.JSON(200, map[string]interface{}{
- "ok": true,
- })
-}
-
-func UpdateIssueMilestone(c *context.Context) {
- issue := getActionIssue(c)
- if c.Written() {
- return
- }
-
- oldMilestoneID := issue.MilestoneID
- milestoneID := c.QueryInt64("id")
- if oldMilestoneID == milestoneID {
- c.JSON(200, map[string]interface{}{
- "ok": true,
- })
- return
- }
-
- // Not check for invalid milestone id and give responsibility to owners.
- issue.MilestoneID = milestoneID
- if err := models.ChangeMilestoneAssign(c.User, issue, oldMilestoneID); err != nil {
- c.Handle(500, "ChangeMilestoneAssign", err)
- return
- }
-
- c.JSON(200, map[string]interface{}{
- "ok": true,
- })
-}
-
-func UpdateIssueAssignee(c *context.Context) {
- issue := getActionIssue(c)
- if c.Written() {
- return
- }
-
- assigneeID := c.QueryInt64("id")
- if issue.AssigneeID == assigneeID {
- c.JSON(200, map[string]interface{}{
- "ok": true,
- })
- return
- }
-
- if err := issue.ChangeAssignee(c.User, assigneeID); err != nil {
- c.Handle(500, "ChangeAssignee", err)
- return
- }
-
- c.JSON(200, map[string]interface{}{
- "ok": true,
- })
-}
-
-func NewComment(c *context.Context, f form.CreateComment) {
- issue := getActionIssue(c)
- if c.Written() {
- return
- }
-
- var attachments []string
- if setting.AttachmentEnabled {
- attachments = f.Files
- }
-
- if c.HasError() {
- c.Flash.Error(c.Data["ErrorMsg"].(string))
- c.Redirect(fmt.Sprintf("%s/issues/%d", c.Repo.RepoLink, issue.Index))
- return
- }
-
- var err error
- var comment *models.Comment
- defer func() {
- // Check if issue admin/poster changes the status of issue.
- if (c.Repo.IsWriter() || (c.IsLogged && issue.IsPoster(c.User.ID))) &&
- (f.Status == "reopen" || f.Status == "close") &&
- !(issue.IsPull && issue.PullRequest.HasMerged) {
-
- // Duplication and conflict check should apply to reopen pull request.
- var pr *models.PullRequest
-
- if f.Status == "reopen" && issue.IsPull {
- pull := issue.PullRequest
- pr, err = models.GetUnmergedPullRequest(pull.HeadRepoID, pull.BaseRepoID, pull.HeadBranch, pull.BaseBranch)
- if err != nil {
- if !models.IsErrPullRequestNotExist(err) {
- c.ServerError("GetUnmergedPullRequest", err)
- return
- }
- }
-
- // Regenerate patch and test conflict.
- if pr == nil {
- if err = issue.PullRequest.UpdatePatch(); err != nil {
- c.ServerError("UpdatePatch", err)
- return
- }
-
- issue.PullRequest.AddToTaskQueue()
- }
- }
-
- if pr != nil {
- c.Flash.Info(c.Tr("repo.pulls.open_unmerged_pull_exists", pr.Index))
- } else {
- if err = issue.ChangeStatus(c.User, c.Repo.Repository, f.Status == "close"); err != nil {
- log.Error(2, "ChangeStatus: %v", err)
- } else {
- log.Trace("Issue [%d] status changed to closed: %v", issue.ID, issue.IsClosed)
- }
- }
- }
-
- // Redirect to comment hashtag if there is any actual content.
- typeName := "issues"
- if issue.IsPull {
- typeName = "pulls"
- }
- if comment != nil {
- c.RawRedirect(fmt.Sprintf("%s/%s/%d#%s", c.Repo.RepoLink, typeName, issue.Index, comment.HashTag()))
- } else {
- c.Redirect(fmt.Sprintf("%s/%s/%d", c.Repo.RepoLink, typeName, issue.Index))
- }
- }()
-
- // Fix #321: Allow empty comments, as long as we have attachments.
- if len(f.Content) == 0 && len(attachments) == 0 {
- return
- }
-
- comment, err = models.CreateIssueComment(c.User, c.Repo.Repository, issue, f.Content, attachments)
- if err != nil {
- c.ServerError("CreateIssueComment", err)
- return
- }
-
- log.Trace("Comment created: %d/%d/%d", c.Repo.Repository.ID, issue.ID, comment.ID)
-}
-
-func UpdateCommentContent(c *context.Context) {
- comment, err := models.GetCommentByID(c.ParamsInt64(":id"))
- if err != nil {
- c.NotFoundOrServerError("GetCommentByID", models.IsErrCommentNotExist, err)
- return
- }
-
- if c.UserID() != comment.PosterID && !c.Repo.IsAdmin() {
- c.Error(404)
- return
- } else if comment.Type != models.COMMENT_TYPE_COMMENT {
- c.Error(204)
- return
- }
-
- oldContent := comment.Content
- comment.Content = c.Query("content")
- if len(comment.Content) == 0 {
- c.JSON(200, map[string]interface{}{
- "content": "",
- })
- return
- }
- if err = models.UpdateComment(c.User, comment, oldContent); err != nil {
- c.Handle(500, "UpdateComment", err)
- return
- }
-
- c.JSON(200, map[string]string{
- "content": string(markup.Markdown(comment.Content, c.Query("context"), c.Repo.Repository.ComposeMetas())),
- })
-}
-
-func DeleteComment(c *context.Context) {
- comment, err := models.GetCommentByID(c.ParamsInt64(":id"))
- if err != nil {
- c.NotFoundOrServerError("GetCommentByID", models.IsErrCommentNotExist, err)
- return
- }
-
- if c.UserID() != comment.PosterID && !c.Repo.IsAdmin() {
- c.Error(404)
- return
- } else if comment.Type != models.COMMENT_TYPE_COMMENT {
- c.Error(204)
- return
- }
-
- if err = models.DeleteCommentByID(c.User, comment.ID); err != nil {
- c.Handle(500, "DeleteCommentByID", err)
- return
- }
-
- c.Status(200)
-}
-
-func Labels(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.labels")
- c.Data["PageIsIssueList"] = true
- c.Data["PageIsLabels"] = true
- c.Data["RequireMinicolors"] = true
- c.Data["LabelTemplates"] = models.LabelTemplates
- c.HTML(200, LABELS)
-}
-
-func InitializeLabels(c *context.Context, f form.InitializeLabels) {
- if c.HasError() {
- c.Redirect(c.Repo.RepoLink + "/labels")
- return
- }
- list, err := models.GetLabelTemplateFile(f.TemplateName)
- if err != nil {
- c.Flash.Error(c.Tr("repo.issues.label_templates.fail_to_load_file", f.TemplateName, err))
- c.Redirect(c.Repo.RepoLink + "/labels")
- return
- }
-
- labels := make([]*models.Label, len(list))
- for i := 0; i < len(list); i++ {
- labels[i] = &models.Label{
- RepoID: c.Repo.Repository.ID,
- Name: list[i][0],
- Color: list[i][1],
- }
- }
- if err := models.NewLabels(labels...); err != nil {
- c.Handle(500, "NewLabels", err)
- return
- }
- c.Redirect(c.Repo.RepoLink + "/labels")
-}
-
-func NewLabel(c *context.Context, f form.CreateLabel) {
- c.Data["Title"] = c.Tr("repo.labels")
- c.Data["PageIsLabels"] = true
-
- if c.HasError() {
- c.Flash.Error(c.Data["ErrorMsg"].(string))
- c.Redirect(c.Repo.RepoLink + "/labels")
- return
- }
-
- l := &models.Label{
- RepoID: c.Repo.Repository.ID,
- Name: f.Title,
- Color: f.Color,
- }
- if err := models.NewLabels(l); err != nil {
- c.Handle(500, "NewLabel", err)
- return
- }
- c.Redirect(c.Repo.RepoLink + "/labels")
-}
-
-func UpdateLabel(c *context.Context, f form.CreateLabel) {
- l, err := models.GetLabelByID(f.ID)
- if err != nil {
- switch {
- case models.IsErrLabelNotExist(err):
- c.Error(404)
- default:
- c.Handle(500, "UpdateLabel", err)
- }
- return
- }
-
- l.Name = f.Title
- l.Color = f.Color
- if err := models.UpdateLabel(l); err != nil {
- c.Handle(500, "UpdateLabel", err)
- return
- }
- c.Redirect(c.Repo.RepoLink + "/labels")
-}
-
-func DeleteLabel(c *context.Context) {
- if err := models.DeleteLabel(c.Repo.Repository.ID, c.QueryInt64("id")); err != nil {
- c.Flash.Error("DeleteLabel: " + err.Error())
- } else {
- c.Flash.Success(c.Tr("repo.issues.label_deletion_success"))
- }
-
- c.JSON(200, map[string]interface{}{
- "redirect": c.Repo.RepoLink + "/labels",
- })
- return
-}
-
-func Milestones(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.milestones")
- c.Data["PageIsIssueList"] = true
- c.Data["PageIsMilestones"] = true
-
- isShowClosed := c.Query("state") == "closed"
- openCount, closedCount := models.MilestoneStats(c.Repo.Repository.ID)
- c.Data["OpenCount"] = openCount
- c.Data["ClosedCount"] = closedCount
-
- page := c.QueryInt("page")
- if page <= 1 {
- page = 1
- }
-
- var total int
- if !isShowClosed {
- total = int(openCount)
- } else {
- total = int(closedCount)
- }
- c.Data["Page"] = paginater.New(total, setting.UI.IssuePagingNum, page, 5)
-
- miles, err := models.GetMilestones(c.Repo.Repository.ID, page, isShowClosed)
- if err != nil {
- c.Handle(500, "GetMilestones", err)
- return
- }
- for _, m := range miles {
- m.NumOpenIssues = int(m.CountIssues(false, false))
- m.NumClosedIssues = int(m.CountIssues(true, false))
- if m.NumOpenIssues+m.NumClosedIssues > 0 {
- m.Completeness = m.NumClosedIssues * 100 / (m.NumOpenIssues + m.NumClosedIssues)
- }
- m.RenderedContent = string(markup.Markdown(m.Content, c.Repo.RepoLink, c.Repo.Repository.ComposeMetas()))
- }
- c.Data["Milestones"] = miles
-
- if isShowClosed {
- c.Data["State"] = "closed"
- } else {
- c.Data["State"] = "open"
- }
-
- c.Data["IsShowClosed"] = isShowClosed
- c.HTML(200, MILESTONE)
-}
-
-func NewMilestone(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.milestones.new")
- c.Data["PageIsIssueList"] = true
- c.Data["PageIsMilestones"] = true
- c.Data["RequireDatetimepicker"] = true
- c.Data["DateLang"] = setting.DateLang(c.Locale.Language())
- c.HTML(200, MILESTONE_NEW)
-}
-
-func NewMilestonePost(c *context.Context, f form.CreateMilestone) {
- c.Data["Title"] = c.Tr("repo.milestones.new")
- c.Data["PageIsIssueList"] = true
- c.Data["PageIsMilestones"] = true
- c.Data["RequireDatetimepicker"] = true
- c.Data["DateLang"] = setting.DateLang(c.Locale.Language())
-
- if c.HasError() {
- c.HTML(200, MILESTONE_NEW)
- return
- }
-
- if len(f.Deadline) == 0 {
- f.Deadline = "9999-12-31"
- }
- deadline, err := time.ParseInLocation("2006-01-02", f.Deadline, time.Local)
- if err != nil {
- c.Data["Err_Deadline"] = true
- c.RenderWithErr(c.Tr("repo.milestones.invalid_due_date_format"), MILESTONE_NEW, &f)
- return
- }
-
- if err = models.NewMilestone(&models.Milestone{
- RepoID: c.Repo.Repository.ID,
- Name: f.Title,
- Content: f.Content,
- Deadline: deadline,
- }); err != nil {
- c.Handle(500, "NewMilestone", err)
- return
- }
-
- c.Flash.Success(c.Tr("repo.milestones.create_success", f.Title))
- c.Redirect(c.Repo.RepoLink + "/milestones")
-}
-
-func EditMilestone(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.milestones.edit")
- c.Data["PageIsMilestones"] = true
- c.Data["PageIsEditMilestone"] = true
- c.Data["RequireDatetimepicker"] = true
- c.Data["DateLang"] = setting.DateLang(c.Locale.Language())
-
- m, err := models.GetMilestoneByRepoID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
- if err != nil {
- if models.IsErrMilestoneNotExist(err) {
- c.Handle(404, "", nil)
- } else {
- c.Handle(500, "GetMilestoneByRepoID", err)
- }
- return
- }
- c.Data["title"] = m.Name
- c.Data["content"] = m.Content
- if len(m.DeadlineString) > 0 {
- c.Data["deadline"] = m.DeadlineString
- }
- c.HTML(200, MILESTONE_NEW)
-}
-
-func EditMilestonePost(c *context.Context, f form.CreateMilestone) {
- c.Data["Title"] = c.Tr("repo.milestones.edit")
- c.Data["PageIsMilestones"] = true
- c.Data["PageIsEditMilestone"] = true
- c.Data["RequireDatetimepicker"] = true
- c.Data["DateLang"] = setting.DateLang(c.Locale.Language())
-
- if c.HasError() {
- c.HTML(200, MILESTONE_NEW)
- return
- }
-
- if len(f.Deadline) == 0 {
- f.Deadline = "9999-12-31"
- }
- deadline, err := time.ParseInLocation("2006-01-02", f.Deadline, time.Local)
- if err != nil {
- c.Data["Err_Deadline"] = true
- c.RenderWithErr(c.Tr("repo.milestones.invalid_due_date_format"), MILESTONE_NEW, &f)
- return
- }
-
- m, err := models.GetMilestoneByRepoID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
- if err != nil {
- if models.IsErrMilestoneNotExist(err) {
- c.Handle(404, "", nil)
- } else {
- c.Handle(500, "GetMilestoneByRepoID", err)
- }
- return
- }
- m.Name = f.Title
- m.Content = f.Content
- m.Deadline = deadline
- if err = models.UpdateMilestone(m); err != nil {
- c.Handle(500, "UpdateMilestone", err)
- return
- }
-
- c.Flash.Success(c.Tr("repo.milestones.edit_success", m.Name))
- c.Redirect(c.Repo.RepoLink + "/milestones")
-}
-
-func ChangeMilestonStatus(c *context.Context) {
- m, err := models.GetMilestoneByRepoID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
- if err != nil {
- if models.IsErrMilestoneNotExist(err) {
- c.Handle(404, "", err)
- } else {
- c.Handle(500, "GetMilestoneByRepoID", err)
- }
- return
- }
-
- switch c.Params(":action") {
- case "open":
- if m.IsClosed {
- if err = models.ChangeMilestoneStatus(m, false); err != nil {
- c.Handle(500, "ChangeMilestoneStatus", err)
- return
- }
- }
- c.Redirect(c.Repo.RepoLink + "/milestones?state=open")
- case "close":
- if !m.IsClosed {
- m.ClosedDate = time.Now()
- if err = models.ChangeMilestoneStatus(m, true); err != nil {
- c.Handle(500, "ChangeMilestoneStatus", err)
- return
- }
- }
- c.Redirect(c.Repo.RepoLink + "/milestones?state=closed")
- default:
- c.Redirect(c.Repo.RepoLink + "/milestones")
- }
-}
-
-func DeleteMilestone(c *context.Context) {
- if err := models.DeleteMilestoneOfRepoByID(c.Repo.Repository.ID, c.QueryInt64("id")); err != nil {
- c.Flash.Error("DeleteMilestoneByRepoID: " + err.Error())
- } else {
- c.Flash.Success(c.Tr("repo.milestones.deletion_success"))
- }
-
- c.JSON(200, map[string]interface{}{
- "redirect": c.Repo.RepoLink + "/milestones",
- })
-}
diff --git a/routes/repo/pull.go b/routes/repo/pull.go
deleted file mode 100644
index a5f76654..00000000
--- a/routes/repo/pull.go
+++ /dev/null
@@ -1,771 +0,0 @@
-// Copyright 2014 The Gogs Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package repo
-
-import (
- "container/list"
- "path"
- "strings"
-
- "github.com/unknwon/com"
- log "gopkg.in/clog.v1"
-
- "github.com/gogs/git-module"
-
- "gogs.io/gogs/models"
- "gogs.io/gogs/models/errors"
- "gogs.io/gogs/pkg/context"
- "gogs.io/gogs/pkg/form"
- "gogs.io/gogs/pkg/setting"
- "gogs.io/gogs/pkg/tool"
-)
-
-const (
- FORK = "repo/pulls/fork"
- COMPARE_PULL = "repo/pulls/compare"
- PULL_COMMITS = "repo/pulls/commits"
- PULL_FILES = "repo/pulls/files"
-
- PULL_REQUEST_TEMPLATE_KEY = "PullRequestTemplate"
-)
-
-var (
- PullRequestTemplateCandidates = []string{
- "PULL_REQUEST.md",
- ".gogs/PULL_REQUEST.md",
- ".github/PULL_REQUEST.md",
- }
-)
-
-func parseBaseRepository(c *context.Context) *models.Repository {
- baseRepo, err := models.GetRepositoryByID(c.ParamsInt64(":repoid"))
- if err != nil {
- c.NotFoundOrServerError("GetRepositoryByID", errors.IsRepoNotExist, err)
- return nil
- }
-
- if !baseRepo.CanBeForked() || !baseRepo.HasAccess(c.User.ID) {
- c.NotFound()
- return nil
- }
-
- c.Data["repo_name"] = baseRepo.Name
- c.Data["description"] = baseRepo.Description
- c.Data["IsPrivate"] = baseRepo.IsPrivate
-
- if err = baseRepo.GetOwner(); err != nil {
- c.ServerError("GetOwner", err)
- return nil
- }
- c.Data["ForkFrom"] = baseRepo.Owner.Name + "/" + baseRepo.Name
-
- if err := c.User.GetOrganizations(true); err != nil {
- c.ServerError("GetOrganizations", err)
- return nil
- }
- c.Data["Orgs"] = c.User.Orgs
-
- return baseRepo
-}
-
-func Fork(c *context.Context) {
- c.Data["Title"] = c.Tr("new_fork")
-
- parseBaseRepository(c)
- if c.Written() {
- return
- }
-
- c.Data["ContextUser"] = c.User
- c.Success(FORK)
-}
-
-func ForkPost(c *context.Context, f form.CreateRepo) {
- c.Data["Title"] = c.Tr("new_fork")
-
- baseRepo := parseBaseRepository(c)
- if c.Written() {
- return
- }
-
- ctxUser := checkContextUser(c, f.UserID)
- if c.Written() {
- return
- }
- c.Data["ContextUser"] = ctxUser
-
- if c.HasError() {
- c.Success(FORK)
- return
- }
-
- repo, has, err := models.HasForkedRepo(ctxUser.ID, baseRepo.ID)
- if err != nil {
- c.ServerError("HasForkedRepo", err)
- return
- } else if has {
- c.Redirect(repo.Link())
- return
- }
-
- // Check ownership of organization.
- if ctxUser.IsOrganization() && !ctxUser.IsOwnedBy(c.User.ID) {
- c.Error(403)
- return
- }
-
- // Cannot fork to same owner
- if ctxUser.ID == baseRepo.OwnerID {
- c.RenderWithErr(c.Tr("repo.settings.cannot_fork_to_same_owner"), FORK, &f)
- return
- }
-
- repo, err = models.ForkRepository(c.User, ctxUser, baseRepo, f.RepoName, f.Description)
- if err != nil {
- c.Data["Err_RepoName"] = true
- switch {
- case errors.IsReachLimitOfRepo(err):
- c.RenderWithErr(c.Tr("repo.form.reach_limit_of_creation", c.User.RepoCreationNum()), FORK, &f)
- case models.IsErrRepoAlreadyExist(err):
- c.RenderWithErr(c.Tr("repo.settings.new_owner_has_same_repo"), FORK, &f)
- case models.IsErrNameReserved(err):
- c.RenderWithErr(c.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), FORK, &f)
- case models.IsErrNamePatternNotAllowed(err):
- c.RenderWithErr(c.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), FORK, &f)
- default:
- c.ServerError("ForkPost", err)
- }
- return
- }
-
- log.Trace("Repository forked from '%s' -> '%s'", baseRepo.FullName(), repo.FullName())
- c.Redirect(repo.Link())
-}
-
-func checkPullInfo(c *context.Context) *models.Issue {
- issue, err := models.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
- if err != nil {
- c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
- return nil
- }
- c.Data["Title"] = issue.Title
- c.Data["Issue"] = issue
-
- if !issue.IsPull {
- c.Handle(404, "ViewPullCommits", nil)
- return nil
- }
-
- if c.IsLogged {
- // Update issue-user.
- if err = issue.ReadBy(c.User.ID); err != nil {
- c.ServerError("ReadBy", err)
- return nil
- }
- }
-
- return issue
-}
-
-func PrepareMergedViewPullInfo(c *context.Context, issue *models.Issue) {
- pull := issue.PullRequest
- c.Data["HasMerged"] = true
- c.Data["HeadTarget"] = issue.PullRequest.HeadUserName + "/" + pull.HeadBranch
- c.Data["BaseTarget"] = c.Repo.Owner.Name + "/" + pull.BaseBranch
-
- var err error
- c.Data["NumCommits"], err = c.Repo.GitRepo.CommitsCountBetween(pull.MergeBase, pull.MergedCommitID)
- if err != nil {
- c.ServerError("Repo.GitRepo.CommitsCountBetween", err)
- return
- }
- c.Data["NumFiles"], err = c.Repo.GitRepo.FilesCountBetween(pull.MergeBase, pull.MergedCommitID)
- if err != nil {
- c.ServerError("Repo.GitRepo.FilesCountBetween", err)
- return
- }
-}
-
-func PrepareViewPullInfo(c *context.Context, issue *models.Issue) *git.PullRequestInfo {
- repo := c.Repo.Repository
- pull := issue.PullRequest
-
- c.Data["HeadTarget"] = pull.HeadUserName + "/" + pull.HeadBranch
- c.Data["BaseTarget"] = c.Repo.Owner.Name + "/" + pull.BaseBranch
-
- var (
- headGitRepo *git.Repository
- err error
- )
-
- if pull.HeadRepo != nil {
- headGitRepo, err = git.OpenRepository(pull.HeadRepo.RepoPath())
- if err != nil {
- c.ServerError("OpenRepository", err)
- return nil
- }
- }
-
- if pull.HeadRepo == nil || !headGitRepo.IsBranchExist(pull.HeadBranch) {
- c.Data["IsPullReuqestBroken"] = true
- c.Data["HeadTarget"] = "deleted"
- c.Data["NumCommits"] = 0
- c.Data["NumFiles"] = 0
- return nil
- }
-
- prInfo, err := headGitRepo.GetPullRequestInfo(models.RepoPath(repo.Owner.Name, repo.Name),
- pull.BaseBranch, pull.HeadBranch)
- if err != nil {
- if strings.Contains(err.Error(), "fatal: Not a valid object name") {
- c.Data["IsPullReuqestBroken"] = true
- c.Data["BaseTarget"] = "deleted"
- c.Data["NumCommits"] = 0
- c.Data["NumFiles"] = 0
- return nil
- }
-
- c.ServerError("GetPullRequestInfo", err)
- return nil
- }
- c.Data["NumCommits"] = prInfo.Commits.Len()
- c.Data["NumFiles"] = prInfo.NumFiles
- return prInfo
-}
-
-func ViewPullCommits(c *context.Context) {
- c.Data["PageIsPullList"] = true
- c.Data["PageIsPullCommits"] = true
-
- issue := checkPullInfo(c)
- if c.Written() {
- return
- }
- pull := issue.PullRequest
-
- if pull.HeadRepo != nil {
- c.Data["Username"] = pull.HeadUserName
- c.Data["Reponame"] = pull.HeadRepo.Name
- }
-
- var commits *list.List
- if pull.HasMerged {
- PrepareMergedViewPullInfo(c, issue)
- if c.Written() {
- return
- }
- startCommit, err := c.Repo.GitRepo.GetCommit(pull.MergeBase)
- if err != nil {
- c.ServerError("Repo.GitRepo.GetCommit", err)
- return
- }
- endCommit, err := c.Repo.GitRepo.GetCommit(pull.MergedCommitID)
- if err != nil {
- c.ServerError("Repo.GitRepo.GetCommit", err)
- return
- }
- commits, err = c.Repo.GitRepo.CommitsBetween(endCommit, startCommit)
- if err != nil {
- c.ServerError("Repo.GitRepo.CommitsBetween", err)
- return
- }
-
- } else {
- prInfo := PrepareViewPullInfo(c, issue)
- if c.Written() {
- return
- } else if prInfo == nil {
- c.NotFound()
- return
- }
- commits = prInfo.Commits
- }
-
- commits = models.ValidateCommitsWithEmails(commits)
- c.Data["Commits"] = commits
- c.Data["CommitsCount"] = commits.Len()
-
- c.Success(PULL_COMMITS)
-}
-
-func ViewPullFiles(c *context.Context) {
- c.Data["PageIsPullList"] = true
- c.Data["PageIsPullFiles"] = true
-
- issue := checkPullInfo(c)
- if c.Written() {
- return
- }
- pull := issue.PullRequest
-
- var (
- diffRepoPath string
- startCommitID string
- endCommitID string
- gitRepo *git.Repository
- )
-
- if pull.HasMerged {
- PrepareMergedViewPullInfo(c, issue)
- if c.Written() {
- return
- }
-
- diffRepoPath = c.Repo.GitRepo.Path
- startCommitID = pull.MergeBase
- endCommitID = pull.MergedCommitID
- gitRepo = c.Repo.GitRepo
- } else {
- prInfo := PrepareViewPullInfo(c, issue)
- if c.Written() {
- return
- } else if prInfo == nil {
- c.Handle(404, "ViewPullFiles", nil)
- return
- }
-
- headRepoPath := models.RepoPath(pull.HeadUserName, pull.HeadRepo.Name)
-
- headGitRepo, err := git.OpenRepository(headRepoPath)
- if err != nil {
- c.ServerError("OpenRepository", err)
- return
- }
-
- headCommitID, err := headGitRepo.GetBranchCommitID(pull.HeadBranch)
- if err != nil {
- c.ServerError("GetBranchCommitID", err)
- return
- }
-
- diffRepoPath = headRepoPath
- startCommitID = prInfo.MergeBase
- endCommitID = headCommitID
- gitRepo = headGitRepo
- }
-
- diff, err := models.GetDiffRange(diffRepoPath,
- startCommitID, endCommitID, setting.Git.MaxGitDiffLines,
- setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles)
- if err != nil {
- c.ServerError("GetDiffRange", err)
- return
- }
- c.Data["Diff"] = diff
- c.Data["DiffNotAvailable"] = diff.NumFiles() == 0
-
- commit, err := gitRepo.GetCommit(endCommitID)
- if err != nil {
- c.ServerError("GetCommit", err)
- return
- }
-
- setEditorconfigIfExists(c)
- if c.Written() {
- return
- }
-
- c.Data["IsSplitStyle"] = c.Query("style") == "split"
- c.Data["IsImageFile"] = commit.IsImageFile
-
- // It is possible head repo has been deleted for merged pull requests
- if pull.HeadRepo != nil {
- c.Data["Username"] = pull.HeadUserName
- c.Data["Reponame"] = pull.HeadRepo.Name
-
- headTarget := path.Join(pull.HeadUserName, pull.HeadRepo.Name)
- c.Data["SourcePath"] = setting.AppSubURL + "/" + path.Join(headTarget, "src", endCommitID)
- c.Data["BeforeSourcePath"] = setting.AppSubURL + "/" + path.Join(headTarget, "src", startCommitID)
- c.Data["RawPath"] = setting.AppSubURL + "/" + path.Join(headTarget, "raw", endCommitID)
- }
-
- c.Data["RequireHighlightJS"] = true
- c.Success(PULL_FILES)
-}
-
-func MergePullRequest(c *context.Context) {
- issue := checkPullInfo(c)
- if c.Written() {
- return
- }
- if issue.IsClosed {
- c.NotFound()
- return
- }
-
- pr, err := models.GetPullRequestByIssueID(issue.ID)
- if err != nil {
- c.NotFoundOrServerError("GetPullRequestByIssueID", models.IsErrPullRequestNotExist, err)
- return
- }
-
- if !pr.CanAutoMerge() || pr.HasMerged {
- c.NotFound()
- return
- }
-
- pr.Issue = issue
- pr.Issue.Repo = c.Repo.Repository
- if err = pr.Merge(c.User, c.Repo.GitRepo, models.MergeStyle(c.Query("merge_style")), c.Query("commit_description")); err != nil {
- c.ServerError("Merge", err)
- return
- }
-
- log.Trace("Pull request merged: %d", pr.ID)
- c.Redirect(c.Repo.RepoLink + "/pulls/" + com.ToStr(pr.Index))
-}
-
-func ParseCompareInfo(c *context.Context) (*models.User, *models.Repository, *git.Repository, *git.PullRequestInfo, string, string) {
- baseRepo := c.Repo.Repository
-
- // Get compared branches information
- // format: <base branch>...[<head repo>:]<head branch>
- // base<-head: master...head:feature
- // same repo: master...feature
- infos := strings.Split(c.Params("*"), "...")
- if len(infos) != 2 {
- log.Trace("ParseCompareInfo[%d]: not enough compared branches information %s", baseRepo.ID, infos)
- c.NotFound()
- return nil, nil, nil, nil, "", ""
- }
-
- baseBranch := infos[0]
- c.Data["BaseBranch"] = baseBranch
-
- var (
- headUser *models.User
- headBranch string
- isSameRepo bool
- err error
- )
-
- // If there is no head repository, it means pull request between same repository.
- headInfos := strings.Split(infos[1], ":")
- if len(headInfos) == 1 {
- isSameRepo = true
- headUser = c.Repo.Owner
- headBranch = headInfos[0]
-
- } else if len(headInfos) == 2 {
- headUser, err = models.GetUserByName(headInfos[0])
- if err != nil {
- c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
- return nil, nil, nil, nil, "", ""
- }
- headBranch = headInfos[1]
- isSameRepo = headUser.ID == baseRepo.OwnerID
-
- } else {
- c.NotFound()
- return nil, nil, nil, nil, "", ""
- }
- c.Data["HeadUser"] = headUser
- c.Data["HeadBranch"] = headBranch
- c.Repo.PullRequest.SameRepo = isSameRepo
-
- // Check if base branch is valid.
- if !c.Repo.GitRepo.IsBranchExist(baseBranch) {
- c.NotFound()
- return nil, nil, nil, nil, "", ""
- }
-
- var (
- headRepo *models.Repository
- headGitRepo *git.Repository
- )
-
- // In case user included redundant head user name for comparison in same repository,
- // no need to check the fork relation.
- if !isSameRepo {
- var has bool
- headRepo, has, err = models.HasForkedRepo(headUser.ID, baseRepo.ID)
- if err != nil {
- c.ServerError("HasForkedRepo", err)
- 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)
- c.NotFound()
- return nil, nil, nil, nil, "", ""
- }
-
- headGitRepo, err = git.OpenRepository(models.RepoPath(headUser.Name, headRepo.Name))
- if err != nil {
- c.ServerError("OpenRepository", err)
- return nil, nil, nil, nil, "", ""
- }
- } else {
- headRepo = c.Repo.Repository
- headGitRepo = c.Repo.GitRepo
- }
-
- if !c.User.IsWriterOfRepo(headRepo) && !c.User.IsAdmin {
- log.Trace("ParseCompareInfo [base_repo_id: %d]: does not have write access or site admin", baseRepo.ID)
- c.NotFound()
- return nil, nil, nil, nil, "", ""
- }
-
- // Check if head branch is valid.
- if !headGitRepo.IsBranchExist(headBranch) {
- c.NotFound()
- return nil, nil, nil, nil, "", ""
- }
-
- headBranches, err := headGitRepo.GetBranches()
- if err != nil {
- c.ServerError("GetBranches", err)
- return nil, nil, nil, nil, "", ""
- }
- c.Data["HeadBranches"] = headBranches
-
- prInfo, err := headGitRepo.GetPullRequestInfo(models.RepoPath(baseRepo.Owner.Name, baseRepo.Name), baseBranch, headBranch)
- if err != nil {
- if git.IsErrNoMergeBase(err) {
- c.Data["IsNoMergeBase"] = true
- c.Success(COMPARE_PULL)
- } else {
- c.ServerError("GetPullRequestInfo", err)
- }
- return nil, nil, nil, nil, "", ""
- }
- c.Data["BeforeCommitID"] = prInfo.MergeBase
-
- return headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch
-}
-
-func PrepareCompareDiff(
- c *context.Context,
- headUser *models.User,
- headRepo *models.Repository,
- headGitRepo *git.Repository,
- prInfo *git.PullRequestInfo,
- baseBranch, headBranch string) bool {
-
- var (
- repo = c.Repo.Repository
- err error
- )
-
- // Get diff information.
- c.Data["CommitRepoLink"] = headRepo.Link()
-
- headCommitID, err := headGitRepo.GetBranchCommitID(headBranch)
- if err != nil {
- c.ServerError("GetBranchCommitID", err)
- return false
- }
- c.Data["AfterCommitID"] = headCommitID
-
- if headCommitID == prInfo.MergeBase {
- c.Data["IsNothingToCompare"] = true
- return true
- }
-
- diff, err := models.GetDiffRange(models.RepoPath(headUser.Name, headRepo.Name),
- prInfo.MergeBase, headCommitID, setting.Git.MaxGitDiffLines,
- setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles)
- if err != nil {
- c.ServerError("GetDiffRange", err)
- return false
- }
- c.Data["Diff"] = diff
- c.Data["DiffNotAvailable"] = diff.NumFiles() == 0
-
- headCommit, err := headGitRepo.GetCommit(headCommitID)
- if err != nil {
- c.ServerError("GetCommit", err)
- return false
- }
-
- prInfo.Commits = models.ValidateCommitsWithEmails(prInfo.Commits)
- c.Data["Commits"] = prInfo.Commits
- c.Data["CommitCount"] = prInfo.Commits.Len()
- c.Data["Username"] = headUser.Name
- c.Data["Reponame"] = headRepo.Name
- c.Data["IsImageFile"] = headCommit.IsImageFile
-
- headTarget := path.Join(headUser.Name, repo.Name)
- c.Data["SourcePath"] = setting.AppSubURL + "/" + path.Join(headTarget, "src", headCommitID)
- c.Data["BeforeSourcePath"] = setting.AppSubURL + "/" + path.Join(headTarget, "src", prInfo.MergeBase)
- c.Data["RawPath"] = setting.AppSubURL + "/" + path.Join(headTarget, "raw", headCommitID)
- return false
-}
-
-func CompareAndPullRequest(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.pulls.compare_changes")
- c.Data["PageIsComparePull"] = true
- c.Data["IsDiffCompare"] = true
- c.Data["RequireHighlightJS"] = true
- setTemplateIfExists(c, PULL_REQUEST_TEMPLATE_KEY, PullRequestTemplateCandidates)
- renderAttachmentSettings(c)
-
- headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch := ParseCompareInfo(c)
- if c.Written() {
- return
- }
-
- pr, err := models.GetUnmergedPullRequest(headRepo.ID, c.Repo.Repository.ID, headBranch, baseBranch)
- if err != nil {
- if !models.IsErrPullRequestNotExist(err) {
- c.ServerError("GetUnmergedPullRequest", err)
- return
- }
- } else {
- c.Data["HasPullRequest"] = true
- c.Data["PullRequest"] = pr
- c.Success(COMPARE_PULL)
- return
- }
-
- nothingToCompare := PrepareCompareDiff(c, headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch)
- if c.Written() {
- return
- }
-
- if !nothingToCompare {
- // Setup information for new form.
- RetrieveRepoMetas(c, c.Repo.Repository)
- if c.Written() {
- return
- }
- }
-
- setEditorconfigIfExists(c)
- if c.Written() {
- return
- }
-
- c.Data["IsSplitStyle"] = c.Query("style") == "split"
- c.Success(COMPARE_PULL)
-}
-
-func CompareAndPullRequestPost(c *context.Context, f form.NewIssue) {
- c.Data["Title"] = c.Tr("repo.pulls.compare_changes")
- c.Data["PageIsComparePull"] = true
- c.Data["IsDiffCompare"] = true
- c.Data["RequireHighlightJS"] = true
- renderAttachmentSettings(c)
-
- var (
- repo = c.Repo.Repository
- attachments []string
- )
-
- headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch := ParseCompareInfo(c)
- if c.Written() {
- return
- }
-
- labelIDs, milestoneID, assigneeID := ValidateRepoMetas(c, f)
- if c.Written() {
- return
- }
-
- if setting.AttachmentEnabled {
- attachments = f.Files
- }
-
- if c.HasError() {
- form.Assign(f, c.Data)
-
- // This stage is already stop creating new pull request, so it does not matter if it has
- // something to compare or not.
- PrepareCompareDiff(c, headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch)
- if c.Written() {
- return
- }
-
- c.Success(COMPARE_PULL)
- return
- }
-
- patch, err := headGitRepo.GetPatch(prInfo.MergeBase, headBranch)
- if err != nil {
- c.ServerError("GetPatch", err)
- return
- }
-
- pullIssue := &models.Issue{
- RepoID: repo.ID,
- Index: repo.NextIssueIndex(),
- Title: f.Title,
- PosterID: c.User.ID,
- Poster: c.User,
- MilestoneID: milestoneID,
- AssigneeID: assigneeID,
- IsPull: true,
- Content: f.Content,
- }
- pullRequest := &models.PullRequest{
- HeadRepoID: headRepo.ID,
- BaseRepoID: repo.ID,
- HeadUserName: headUser.Name,
- HeadBranch: headBranch,
- BaseBranch: baseBranch,
- HeadRepo: headRepo,
- BaseRepo: repo,
- MergeBase: prInfo.MergeBase,
- Type: models.PULL_REQUEST_GOGS,
- }
- // FIXME: check error in the case two people send pull request at almost same time, give nice error prompt
- // instead of 500.
- if err := models.NewPullRequest(repo, pullIssue, labelIDs, attachments, pullRequest, patch); err != nil {
- c.ServerError("NewPullRequest", err)
- return
- } else if err := pullRequest.PushToBaseRepo(); err != nil {
- c.ServerError("PushToBaseRepo", err)
- return
- }
-
- log.Trace("Pull request created: %d/%d", repo.ID, pullIssue.ID)
- c.Redirect(c.Repo.RepoLink + "/pulls/" + com.ToStr(pullIssue.Index))
-}
-
-func parseOwnerAndRepo(c *context.Context) (*models.User, *models.Repository) {
- owner, err := models.GetUserByName(c.Params(":username"))
- if err != nil {
- c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
- return nil, nil
- }
-
- repo, err := models.GetRepositoryByName(owner.ID, c.Params(":reponame"))
- if err != nil {
- c.NotFoundOrServerError("GetRepositoryByName", errors.IsRepoNotExist, err)
- return nil, nil
- }
-
- return owner, repo
-}
-
-func TriggerTask(c *context.Context) {
- pusherID := c.QueryInt64("pusher")
- branch := c.Query("branch")
- secret := c.Query("secret")
- if len(branch) == 0 || len(secret) == 0 || pusherID <= 0 {
- c.Error(404)
- log.Trace("TriggerTask: branch or secret is empty, or pusher ID is not valid")
- return
- }
- owner, repo := parseOwnerAndRepo(c)
- if c.Written() {
- return
- }
- if secret != tool.MD5(owner.Salt) {
- c.Error(404)
- log.Trace("TriggerTask [%s/%s]: invalid secret", owner.Name, repo.Name)
- return
- }
-
- pusher, err := models.GetUserByID(pusherID)
- if err != nil {
- c.NotFoundOrServerError("GetUserByID", errors.IsUserNotExist, err)
- return
- }
-
- log.Trace("TriggerTask '%s/%s' by '%s'", repo.Name, branch, pusher.Name)
-
- go models.HookQueue.Add(repo.ID)
- go models.AddTestPullRequestTask(pusher, repo.ID, branch, true)
- c.Status(202)
-}
diff --git a/routes/repo/release.go b/routes/repo/release.go
deleted file mode 100644
index 468f8965..00000000
--- a/routes/repo/release.go
+++ /dev/null
@@ -1,332 +0,0 @@
-// Copyright 2014 The Gogs Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package repo
-
-import (
- "fmt"
- "strings"
-
- log "gopkg.in/clog.v1"
-
- "gogs.io/gogs/models"
- "gogs.io/gogs/pkg/context"
- "gogs.io/gogs/pkg/form"
- "gogs.io/gogs/pkg/markup"
- "gogs.io/gogs/pkg/setting"
-)
-
-const (
- RELEASES = "repo/release/list"
- RELEASE_NEW = "repo/release/new"
-)
-
-// calReleaseNumCommitsBehind calculates given release has how many commits behind release target.
-func calReleaseNumCommitsBehind(repoCtx *context.Repository, release *models.Release, countCache map[string]int64) error {
- // Get count if not exists
- if _, ok := countCache[release.Target]; !ok {
- if repoCtx.GitRepo.IsBranchExist(release.Target) {
- commit, err := repoCtx.GitRepo.GetBranchCommit(release.Target)
- if err != nil {
- return fmt.Errorf("GetBranchCommit: %v", err)
- }
- countCache[release.Target], err = commit.CommitsCount()
- if err != nil {
- return fmt.Errorf("CommitsCount: %v", err)
- }
- } else {
- // Use NumCommits of the newest release on that target
- countCache[release.Target] = release.NumCommits
- }
- }
- release.NumCommitsBehind = countCache[release.Target] - release.NumCommits
- return nil
-}
-
-func Releases(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.release.releases")
- c.Data["PageIsViewFiles"] = true
- c.Data["PageIsReleaseList"] = true
-
- tagsResult, err := c.Repo.GitRepo.GetTagsAfter(c.Query("after"), 10)
- if err != nil {
- c.Handle(500, fmt.Sprintf("GetTags '%s'", c.Repo.Repository.RepoPath()), err)
- return
- }
-
- releases, err := models.GetPublishedReleasesByRepoID(c.Repo.Repository.ID, tagsResult.Tags...)
- if err != nil {
- c.Handle(500, "GetPublishedReleasesByRepoID", err)
- return
- }
-
- // Temproray cache commits count of used branches to speed up.
- countCache := make(map[string]int64)
-
- results := make([]*models.Release, len(tagsResult.Tags))
- for i, rawTag := range tagsResult.Tags {
- for j, r := range releases {
- if r == nil || r.TagName != rawTag {
- continue
- }
- releases[j] = nil // Mark as used.
-
- if err = r.LoadAttributes(); err != nil {
- c.Handle(500, "LoadAttributes", err)
- return
- }
-
- if err := calReleaseNumCommitsBehind(c.Repo, r, countCache); err != nil {
- c.Handle(500, "calReleaseNumCommitsBehind", err)
- return
- }
-
- r.Note = string(markup.Markdown(r.Note, c.Repo.RepoLink, c.Repo.Repository.ComposeMetas()))
- results[i] = r
- break
- }
-
- // No published release matches this tag
- if results[i] == nil {
- commit, err := c.Repo.GitRepo.GetTagCommit(rawTag)
- if err != nil {
- c.Handle(500, "GetTagCommit", err)
- return
- }
-
- results[i] = &models.Release{
- Title: rawTag,
- TagName: rawTag,
- Sha1: commit.ID.String(),
- }
-
- results[i].NumCommits, err = commit.CommitsCount()
- if err != nil {
- c.Handle(500, "CommitsCount", err)
- return
- }
- results[i].NumCommitsBehind = c.Repo.CommitsCount - results[i].NumCommits
- }
- }
- models.SortReleases(results)
-
- // Only show drafts if user is viewing the latest page
- var drafts []*models.Release
- if tagsResult.HasLatest {
- drafts, err = models.GetDraftReleasesByRepoID(c.Repo.Repository.ID)
- if err != nil {
- c.Handle(500, "GetDraftReleasesByRepoID", err)
- return
- }
-
- for _, r := range drafts {
- if err = r.LoadAttributes(); err != nil {
- c.Handle(500, "LoadAttributes", err)
- return
- }
-
- if err := calReleaseNumCommitsBehind(c.Repo, r, countCache); err != nil {
- c.Handle(500, "calReleaseNumCommitsBehind", err)
- return
- }
-
- r.Note = string(markup.Markdown(r.Note, c.Repo.RepoLink, c.Repo.Repository.ComposeMetas()))
- }
-
- if len(drafts) > 0 {
- results = append(drafts, results...)
- }
- }
-
- c.Data["Releases"] = results
- c.Data["HasPrevious"] = !tagsResult.HasLatest
- c.Data["ReachEnd"] = tagsResult.ReachEnd
- c.Data["PreviousAfter"] = tagsResult.PreviousAfter
- if len(results) > 0 {
- c.Data["NextAfter"] = results[len(results)-1].TagName
- }
- c.HTML(200, RELEASES)
-}
-
-func renderReleaseAttachmentSettings(c *context.Context) {
- c.Data["RequireDropzone"] = true
- c.Data["IsAttachmentEnabled"] = setting.Release.Attachment.Enabled
- c.Data["AttachmentAllowedTypes"] = strings.Join(setting.Release.Attachment.AllowedTypes, ",")
- c.Data["AttachmentMaxSize"] = setting.Release.Attachment.MaxSize
- c.Data["AttachmentMaxFiles"] = setting.Release.Attachment.MaxFiles
-}
-
-func NewRelease(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.release.new_release")
- c.Data["PageIsReleaseList"] = true
- c.Data["tag_target"] = c.Repo.Repository.DefaultBranch
- renderReleaseAttachmentSettings(c)
- c.HTML(200, RELEASE_NEW)
-}
-
-func NewReleasePost(c *context.Context, f form.NewRelease) {
- c.Data["Title"] = c.Tr("repo.release.new_release")
- c.Data["PageIsReleaseList"] = true
- renderReleaseAttachmentSettings(c)
-
- if c.HasError() {
- c.HTML(200, RELEASE_NEW)
- return
- }
-
- if !c.Repo.GitRepo.IsBranchExist(f.Target) {
- c.RenderWithErr(c.Tr("form.target_branch_not_exist"), RELEASE_NEW, &f)
- return
- }
-
- // Use current time if tag not yet exist, otherwise get time from Git
- var tagCreatedUnix int64
- tag, err := c.Repo.GitRepo.GetTag(f.TagName)
- if err == nil {
- commit, err := tag.Commit()
- if err == nil {
- tagCreatedUnix = commit.Author.When.Unix()
- }
- }
-
- commit, err := c.Repo.GitRepo.GetBranchCommit(f.Target)
- if err != nil {
- c.Handle(500, "GetBranchCommit", err)
- return
- }
-
- commitsCount, err := commit.CommitsCount()
- if err != nil {
- c.Handle(500, "CommitsCount", err)
- return
- }
-
- var attachments []string
- if setting.Release.Attachment.Enabled {
- attachments = f.Files
- }
-
- rel := &models.Release{
- RepoID: c.Repo.Repository.ID,
- PublisherID: c.User.ID,
- Title: f.Title,
- TagName: f.TagName,
- Target: f.Target,
- Sha1: commit.ID.String(),
- NumCommits: commitsCount,
- Note: f.Content,
- IsDraft: len(f.Draft) > 0,
- IsPrerelease: f.Prerelease,
- CreatedUnix: tagCreatedUnix,
- }
- if err = models.NewRelease(c.Repo.GitRepo, rel, attachments); err != nil {
- c.Data["Err_TagName"] = true
- switch {
- case models.IsErrReleaseAlreadyExist(err):
- c.RenderWithErr(c.Tr("repo.release.tag_name_already_exist"), RELEASE_NEW, &f)
- case models.IsErrInvalidTagName(err):
- c.RenderWithErr(c.Tr("repo.release.tag_name_invalid"), RELEASE_NEW, &f)
- default:
- c.Handle(500, "NewRelease", err)
- }
- return
- }
- log.Trace("Release created: %s/%s:%s", c.User.LowerName, c.Repo.Repository.Name, f.TagName)
-
- c.Redirect(c.Repo.RepoLink + "/releases")
-}
-
-func EditRelease(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.release.edit_release")
- c.Data["PageIsReleaseList"] = true
- c.Data["PageIsEditRelease"] = true
- renderReleaseAttachmentSettings(c)
-
- tagName := c.Params("*")
- rel, err := models.GetRelease(c.Repo.Repository.ID, tagName)
- if err != nil {
- if models.IsErrReleaseNotExist(err) {
- c.Handle(404, "GetRelease", err)
- } else {
- c.Handle(500, "GetRelease", err)
- }
- return
- }
- c.Data["ID"] = rel.ID
- c.Data["tag_name"] = rel.TagName
- c.Data["tag_target"] = rel.Target
- c.Data["title"] = rel.Title
- c.Data["content"] = rel.Note
- c.Data["attachments"] = rel.Attachments
- c.Data["prerelease"] = rel.IsPrerelease
- c.Data["IsDraft"] = rel.IsDraft
-
- c.HTML(200, RELEASE_NEW)
-}
-
-func EditReleasePost(c *context.Context, f form.EditRelease) {
- c.Data["Title"] = c.Tr("repo.release.edit_release")
- c.Data["PageIsReleaseList"] = true
- c.Data["PageIsEditRelease"] = true
- renderReleaseAttachmentSettings(c)
-
- tagName := c.Params("*")
- rel, err := models.GetRelease(c.Repo.Repository.ID, tagName)
- if err != nil {
- if models.IsErrReleaseNotExist(err) {
- c.Handle(404, "GetRelease", err)
- } else {
- c.Handle(500, "GetRelease", err)
- }
- return
- }
- c.Data["tag_name"] = rel.TagName
- c.Data["tag_target"] = rel.Target
- c.Data["title"] = rel.Title
- c.Data["content"] = rel.Note
- c.Data["attachments"] = rel.Attachments
- c.Data["prerelease"] = rel.IsPrerelease
- c.Data["IsDraft"] = rel.IsDraft
-
- if c.HasError() {
- c.HTML(200, RELEASE_NEW)
- return
- }
-
- var attachments []string
- if setting.Release.Attachment.Enabled {
- attachments = f.Files
- }
-
- isPublish := rel.IsDraft && len(f.Draft) == 0
- rel.Title = f.Title
- rel.Note = f.Content
- rel.IsDraft = len(f.Draft) > 0
- rel.IsPrerelease = f.Prerelease
- if err = models.UpdateRelease(c.User, c.Repo.GitRepo, rel, isPublish, attachments); err != nil {
- c.Handle(500, "UpdateRelease", err)
- return
- }
- c.Redirect(c.Repo.RepoLink + "/releases")
-}
-
-func UploadReleaseAttachment(c *context.Context) {
- if !setting.Release.Attachment.Enabled {
- c.NotFound()
- return
- }
- uploadAttachment(c, setting.Release.Attachment.AllowedTypes)
-}
-
-func DeleteRelease(c *context.Context) {
- if err := models.DeleteReleaseOfRepoByID(c.Repo.Repository.ID, c.QueryInt64("id")); err != nil {
- c.Flash.Error("DeleteReleaseByID: " + err.Error())
- } else {
- c.Flash.Success(c.Tr("repo.release.deletion_success"))
- }
-
- c.JSON(200, map[string]interface{}{
- "redirect": c.Repo.RepoLink + "/releases",
- })
-}
diff --git a/routes/repo/repo.go b/routes/repo/repo.go
deleted file mode 100644
index 19c1e7fd..00000000
--- a/routes/repo/repo.go
+++ /dev/null
@@ -1,342 +0,0 @@
-// Copyright 2014 The Gogs Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package repo
-
-import (
- "fmt"
- "os"
- "path"
- "strings"
-
- "github.com/unknwon/com"
- log "gopkg.in/clog.v1"
-
- "github.com/gogs/git-module"
-
- "gogs.io/gogs/models"
- "gogs.io/gogs/models/errors"
- "gogs.io/gogs/pkg/context"
- "gogs.io/gogs/pkg/form"
- "gogs.io/gogs/pkg/setting"
- "gogs.io/gogs/pkg/tool"
-)
-
-const (
- CREATE = "repo/create"
- MIGRATE = "repo/migrate"
-)
-
-func MustBeNotBare(c *context.Context) {
- if c.Repo.Repository.IsBare {
- c.Handle(404, "MustBeNotBare", nil)
- }
-}
-
-func checkContextUser(c *context.Context, uid int64) *models.User {
- orgs, err := models.GetOwnedOrgsByUserIDDesc(c.User.ID, "updated_unix")
- if err != nil {
- c.Handle(500, "GetOwnedOrgsByUserIDDesc", err)
- return nil
- }
- c.Data["Orgs"] = orgs
-
- // Not equal means current user is an organization.
- if uid == c.User.ID || uid == 0 {
- return c.User
- }
-
- org, err := models.GetUserByID(uid)
- if errors.IsUserNotExist(err) {
- return c.User
- }
-
- if err != nil {
- c.Handle(500, "GetUserByID", fmt.Errorf("[%d]: %v", uid, err))
- return nil
- }
-
- // Check ownership of organization.
- if !org.IsOrganization() || !(c.User.IsAdmin || org.IsOwnedBy(c.User.ID)) {
- c.Error(403)
- return nil
- }
- return org
-}
-
-func Create(c *context.Context) {
- c.Title("new_repo")
- c.RequireAutosize()
-
- // Give default value for template to render.
- c.Data["Gitignores"] = models.Gitignores
- c.Data["Licenses"] = models.Licenses
- c.Data["Readmes"] = models.Readmes
- c.Data["readme"] = "Default"
- c.Data["private"] = c.User.LastRepoVisibility
- c.Data["IsForcedPrivate"] = setting.Repository.ForcePrivate
-
- ctxUser := checkContextUser(c, c.QueryInt64("org"))
- if c.Written() {
- return
- }
- c.Data["ContextUser"] = ctxUser
-
- c.HTML(200, CREATE)
-}
-
-func handleCreateError(c *context.Context, owner *models.User, err error, name, tpl string, form interface{}) {
- switch {
- case errors.IsReachLimitOfRepo(err):
- c.RenderWithErr(c.Tr("repo.form.reach_limit_of_creation", owner.RepoCreationNum()), tpl, form)
- case models.IsErrRepoAlreadyExist(err):
- c.Data["Err_RepoName"] = true
- c.RenderWithErr(c.Tr("form.repo_name_been_taken"), tpl, form)
- case models.IsErrNameReserved(err):
- c.Data["Err_RepoName"] = true
- c.RenderWithErr(c.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), tpl, form)
- case models.IsErrNamePatternNotAllowed(err):
- c.Data["Err_RepoName"] = true
- c.RenderWithErr(c.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), tpl, form)
- default:
- c.Handle(500, name, err)
- }
-}
-
-func CreatePost(c *context.Context, f form.CreateRepo) {
- c.Data["Title"] = c.Tr("new_repo")
-
- c.Data["Gitignores"] = models.Gitignores
- c.Data["Licenses"] = models.Licenses
- c.Data["Readmes"] = models.Readmes
-
- ctxUser := checkContextUser(c, f.UserID)
- if c.Written() {
- return
- }
- c.Data["ContextUser"] = ctxUser
-
- if c.HasError() {
- c.HTML(200, CREATE)
- return
- }
-
- repo, err := models.CreateRepository(c.User, ctxUser, models.CreateRepoOptions{
- Name: f.RepoName,
- Description: f.Description,
- Gitignores: f.Gitignores,
- License: f.License,
- Readme: f.Readme,
- IsPrivate: f.Private || setting.Repository.ForcePrivate,
- AutoInit: f.AutoInit,
- })
- if err == nil {
- log.Trace("Repository created [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name)
- c.Redirect(setting.AppSubURL + "/" + ctxUser.Name + "/" + repo.Name)
- return
- }
-
- if repo != nil {
- if errDelete := models.DeleteRepository(ctxUser.ID, repo.ID); errDelete != nil {
- log.Error(4, "DeleteRepository: %v", errDelete)
- }
- }
-
- handleCreateError(c, ctxUser, err, "CreatePost", CREATE, &f)
-}
-
-func Migrate(c *context.Context) {
- c.Data["Title"] = c.Tr("new_migrate")
- c.Data["private"] = c.User.LastRepoVisibility
- c.Data["IsForcedPrivate"] = setting.Repository.ForcePrivate
- c.Data["mirror"] = c.Query("mirror") == "1"
-
- ctxUser := checkContextUser(c, c.QueryInt64("org"))
- if c.Written() {
- return
- }
- c.Data["ContextUser"] = ctxUser
-
- c.HTML(200, MIGRATE)
-}
-
-func MigratePost(c *context.Context, f form.MigrateRepo) {
- c.Data["Title"] = c.Tr("new_migrate")
-
- ctxUser := checkContextUser(c, f.Uid)
- if c.Written() {
- return
- }
- c.Data["ContextUser"] = ctxUser
-
- if c.HasError() {
- c.HTML(200, MIGRATE)
- return
- }
-
- remoteAddr, err := f.ParseRemoteAddr(c.User)
- if err != nil {
- if models.IsErrInvalidCloneAddr(err) {
- c.Data["Err_CloneAddr"] = true
- addrErr := err.(models.ErrInvalidCloneAddr)
- switch {
- case addrErr.IsURLError:
- c.RenderWithErr(c.Tr("form.url_error"), MIGRATE, &f)
- case addrErr.IsPermissionDenied:
- c.RenderWithErr(c.Tr("repo.migrate.permission_denied"), MIGRATE, &f)
- case addrErr.IsInvalidPath:
- c.RenderWithErr(c.Tr("repo.migrate.invalid_local_path"), MIGRATE, &f)
- default:
- c.Handle(500, "Unknown error", err)
- }
- } else {
- c.Handle(500, "ParseRemoteAddr", err)
- }
- return
- }
-
- repo, err := models.MigrateRepository(c.User, ctxUser, models.MigrateRepoOptions{
- Name: f.RepoName,
- Description: f.Description,
- IsPrivate: f.Private || setting.Repository.ForcePrivate,
- IsMirror: f.Mirror,
- RemoteAddr: remoteAddr,
- })
- if err == nil {
- log.Trace("Repository migrated [%d]: %s/%s", repo.ID, ctxUser.Name, f.RepoName)
- c.Redirect(setting.AppSubURL + "/" + ctxUser.Name + "/" + f.RepoName)
- return
- }
-
- if repo != nil {
- if errDelete := models.DeleteRepository(ctxUser.ID, repo.ID); errDelete != nil {
- log.Error(4, "DeleteRepository: %v", errDelete)
- }
- }
-
- if strings.Contains(err.Error(), "Authentication failed") ||
- strings.Contains(err.Error(), "could not read Username") {
- c.Data["Err_Auth"] = true
- c.RenderWithErr(c.Tr("form.auth_failed", models.HandleMirrorCredentials(err.Error(), true)), MIGRATE, &f)
- return
- } else if strings.Contains(err.Error(), "fatal:") {
- c.Data["Err_CloneAddr"] = true
- c.RenderWithErr(c.Tr("repo.migrate.failed", models.HandleMirrorCredentials(err.Error(), true)), MIGRATE, &f)
- return
- }
-
- handleCreateError(c, ctxUser, err, "MigratePost", MIGRATE, &f)
-}
-
-func Action(c *context.Context) {
- var err error
- switch c.Params(":action") {
- case "watch":
- err = models.WatchRepo(c.User.ID, c.Repo.Repository.ID, true)
- case "unwatch":
- if userID := c.QueryInt64("user_id"); userID != 0 {
- if c.User.IsAdmin {
- err = models.WatchRepo(userID, c.Repo.Repository.ID, false)
- }
- } else {
- err = models.WatchRepo(c.User.ID, c.Repo.Repository.ID, false)
- }
- case "star":
- err = models.StarRepo(c.User.ID, c.Repo.Repository.ID, true)
- case "unstar":
- err = models.StarRepo(c.User.ID, c.Repo.Repository.ID, false)
- case "desc": // FIXME: this is not used
- if !c.Repo.IsOwner() {
- c.NotFound()
- return
- }
-
- c.Repo.Repository.Description = c.Query("desc")
- c.Repo.Repository.Website = c.Query("site")
- err = models.UpdateRepository(c.Repo.Repository, false)
- }
-
- if err != nil {
- c.ServerError(fmt.Sprintf("Action (%s)", c.Params(":action")), err)
- return
- }
-
- redirectTo := c.Query("redirect_to")
- if !tool.IsSameSiteURLPath(redirectTo) {
- redirectTo = c.Repo.RepoLink
- }
- c.Redirect(redirectTo)
-}
-
-func Download(c *context.Context) {
- var (
- uri = c.Params("*")
- refName string
- ext string
- archivePath string
- archiveType git.ArchiveType
- )
-
- switch {
- case strings.HasSuffix(uri, ".zip"):
- ext = ".zip"
- archivePath = path.Join(c.Repo.GitRepo.Path, "archives/zip")
- archiveType = git.ZIP
- case strings.HasSuffix(uri, ".tar.gz"):
- ext = ".tar.gz"
- archivePath = path.Join(c.Repo.GitRepo.Path, "archives/targz")
- archiveType = git.TARGZ
- default:
- log.Trace("Unknown format: %s", uri)
- c.Error(404)
- 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)
- return
- }
- }
-
- // Get corresponding commit.
- var (
- commit *git.Commit
- err error
- )
- gitRepo := c.Repo.GitRepo
- if gitRepo.IsBranchExist(refName) {
- commit, err = gitRepo.GetBranchCommit(refName)
- if err != nil {
- c.Handle(500, "GetBranchCommit", err)
- return
- }
- } else if gitRepo.IsTagExist(refName) {
- commit, err = gitRepo.GetTagCommit(refName)
- if err != nil {
- c.Handle(500, "GetTagCommit", err)
- return
- }
- } else if len(refName) >= 7 && len(refName) <= 40 {
- commit, err = gitRepo.GetCommit(refName)
- if err != nil {
- c.NotFound()
- return
- }
- } else {
- c.NotFound()
- return
- }
-
- archivePath = path.Join(archivePath, tool.ShortSHA1(commit.ID.String())+ext)
- if !com.IsFile(archivePath) {
- if err := commit.CreateArchive(archivePath, archiveType); err != nil {
- c.Handle(500, "Download -> CreateArchive "+archivePath, err)
- return
- }
- }
-
- c.ServeFile(archivePath, c.Repo.Repository.Name+"-"+refName+ext)
-}
diff --git a/routes/repo/setting.go b/routes/repo/setting.go
deleted file mode 100644
index 9015916b..00000000
--- a/routes/repo/setting.go
+++ /dev/null
@@ -1,695 +0,0 @@
-// Copyright 2014 The Gogs Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package repo
-
-import (
- "fmt"
- "io/ioutil"
- "strings"
- "time"
-
- "github.com/unknwon/com"
- "github.com/gogs/git-module"
- log "gopkg.in/clog.v1"
-
- "gogs.io/gogs/models"
- "gogs.io/gogs/models/errors"
- "gogs.io/gogs/pkg/context"
- "gogs.io/gogs/pkg/form"
- "gogs.io/gogs/pkg/mailer"
- "gogs.io/gogs/pkg/setting"
- "gogs.io/gogs/pkg/tool"
-)
-
-const (
- SETTINGS_OPTIONS = "repo/settings/options"
- SETTINGS_REPO_AVATAR = "repo/settings/avatar"
- SETTINGS_COLLABORATION = "repo/settings/collaboration"
- SETTINGS_BRANCHES = "repo/settings/branches"
- SETTINGS_PROTECTED_BRANCH = "repo/settings/protected_branch"
- SETTINGS_GITHOOKS = "repo/settings/githooks"
- SETTINGS_GITHOOK_EDIT = "repo/settings/githook_edit"
- SETTINGS_DEPLOY_KEYS = "repo/settings/deploy_keys"
-)
-
-func Settings(c *context.Context) {
- c.Title("repo.settings")
- c.PageIs("SettingsOptions")
- c.RequireAutosize()
- c.Success(SETTINGS_OPTIONS)
-}
-
-func SettingsPost(c *context.Context, f form.RepoSetting) {
- c.Title("repo.settings")
- c.PageIs("SettingsOptions")
- c.RequireAutosize()
-
- repo := c.Repo.Repository
-
- switch c.Query("action") {
- case "update":
- if c.HasError() {
- c.Success(SETTINGS_OPTIONS)
- return
- }
-
- isNameChanged := false
- oldRepoName := repo.Name
- newRepoName := f.RepoName
- // Check if repository name has been changed.
- if repo.LowerName != strings.ToLower(newRepoName) {
- isNameChanged = true
- if err := models.ChangeRepositoryName(c.Repo.Owner, repo.Name, newRepoName); err != nil {
- c.FormErr("RepoName")
- switch {
- case models.IsErrRepoAlreadyExist(err):
- c.RenderWithErr(c.Tr("form.repo_name_been_taken"), SETTINGS_OPTIONS, &f)
- case models.IsErrNameReserved(err):
- c.RenderWithErr(c.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), SETTINGS_OPTIONS, &f)
- case models.IsErrNamePatternNotAllowed(err):
- c.RenderWithErr(c.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), SETTINGS_OPTIONS, &f)
- default:
- c.ServerError("ChangeRepositoryName", err)
- }
- return
- }
-
- log.Trace("Repository name changed: %s/%s -> %s", c.Repo.Owner.Name, repo.Name, newRepoName)
- }
- // In case it's just a case change.
- repo.Name = newRepoName
- repo.LowerName = strings.ToLower(newRepoName)
-
- repo.Description = f.Description
- repo.Website = f.Website
-
- // Visibility of forked repository is forced sync with base repository.
- if repo.IsFork {
- f.Private = repo.BaseRepo.IsPrivate
- }
-
- visibilityChanged := repo.IsPrivate != f.Private
- repo.IsPrivate = f.Private
- if err := models.UpdateRepository(repo, visibilityChanged); err != nil {
- c.ServerError("UpdateRepository", err)
- return
- }
- log.Trace("Repository basic settings updated: %s/%s", c.Repo.Owner.Name, repo.Name)
-
- if isNameChanged {
- if err := models.RenameRepoAction(c.User, oldRepoName, repo); err != nil {
- log.Error(2, "RenameRepoAction: %v", err)
- }
- }
-
- c.Flash.Success(c.Tr("repo.settings.update_settings_success"))
- c.Redirect(repo.Link() + "/settings")
-
- case "mirror":
- if !repo.IsMirror {
- c.NotFound()
- return
- }
-
- if f.Interval > 0 {
- c.Repo.Mirror.EnablePrune = f.EnablePrune
- c.Repo.Mirror.Interval = f.Interval
- c.Repo.Mirror.NextSync = time.Now().Add(time.Duration(f.Interval) * time.Hour)
- if err := models.UpdateMirror(c.Repo.Mirror); err != nil {
- c.ServerError("UpdateMirror", err)
- return
- }
- }
- if err := c.Repo.Mirror.SaveAddress(f.MirrorAddress); err != nil {
- c.ServerError("SaveAddress", err)
- return
- }
-
- c.Flash.Success(c.Tr("repo.settings.update_settings_success"))
- c.Redirect(repo.Link() + "/settings")
-
- case "mirror-sync":
- if !repo.IsMirror {
- c.NotFound()
- return
- }
-
- go models.MirrorQueue.Add(repo.ID)
- c.Flash.Info(c.Tr("repo.settings.mirror_sync_in_progress"))
- c.Redirect(repo.Link() + "/settings")
-
- case "advanced":
- repo.EnableWiki = f.EnableWiki
- repo.AllowPublicWiki = f.AllowPublicWiki
- repo.EnableExternalWiki = f.EnableExternalWiki
- repo.ExternalWikiURL = f.ExternalWikiURL
- repo.EnableIssues = f.EnableIssues
- repo.AllowPublicIssues = f.AllowPublicIssues
- repo.EnableExternalTracker = f.EnableExternalTracker
- repo.ExternalTrackerURL = f.ExternalTrackerURL
- repo.ExternalTrackerFormat = f.TrackerURLFormat
- repo.ExternalTrackerStyle = f.TrackerIssueStyle
- repo.EnablePulls = f.EnablePulls
- repo.PullsIgnoreWhitespace = f.PullsIgnoreWhitespace
- repo.PullsAllowRebase = f.PullsAllowRebase
-
- if err := models.UpdateRepository(repo, false); err != nil {
- c.ServerError("UpdateRepository", err)
- return
- }
- log.Trace("Repository advanced settings updated: %s/%s", c.Repo.Owner.Name, repo.Name)
-
- c.Flash.Success(c.Tr("repo.settings.update_settings_success"))
- c.Redirect(c.Repo.RepoLink + "/settings")
-
- case "convert":
- if !c.Repo.IsOwner() {
- c.NotFound()
- return
- }
- if repo.Name != f.RepoName {
- c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil)
- return
- }
-
- if c.Repo.Owner.IsOrganization() {
- if !c.Repo.Owner.IsOwnedBy(c.User.ID) {
- c.NotFound()
- return
- }
- }
-
- if !repo.IsMirror {
- c.NotFound()
- return
- }
- repo.IsMirror = false
-
- if _, err := models.CleanUpMigrateInfo(repo); err != nil {
- c.ServerError("CleanUpMigrateInfo", err)
- return
- } else if err = models.DeleteMirrorByRepoID(c.Repo.Repository.ID); err != nil {
- c.ServerError("DeleteMirrorByRepoID", err)
- return
- }
- log.Trace("Repository converted from mirror to regular: %s/%s", c.Repo.Owner.Name, repo.Name)
- c.Flash.Success(c.Tr("repo.settings.convert_succeed"))
- c.Redirect(setting.AppSubURL + "/" + c.Repo.Owner.Name + "/" + repo.Name)
-
- case "transfer":
- if !c.Repo.IsOwner() {
- c.NotFound()
- return
- }
- if repo.Name != f.RepoName {
- c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil)
- return
- }
-
- if c.Repo.Owner.IsOrganization() && !c.User.IsAdmin {
- if !c.Repo.Owner.IsOwnedBy(c.User.ID) {
- c.NotFound()
- return
- }
- }
-
- newOwner := c.Query("new_owner_name")
- isExist, err := models.IsUserExist(0, newOwner)
- if err != nil {
- c.ServerError("IsUserExist", err)
- return
- } else if !isExist {
- c.RenderWithErr(c.Tr("form.enterred_invalid_owner_name"), SETTINGS_OPTIONS, nil)
- return
- }
-
- if err = models.TransferOwnership(c.User, newOwner, repo); err != nil {
- if models.IsErrRepoAlreadyExist(err) {
- c.RenderWithErr(c.Tr("repo.settings.new_owner_has_same_repo"), SETTINGS_OPTIONS, nil)
- } else {
- c.ServerError("TransferOwnership", err)
- }
- return
- }
- log.Trace("Repository transfered: %s/%s -> %s", c.Repo.Owner.Name, repo.Name, newOwner)
- c.Flash.Success(c.Tr("repo.settings.transfer_succeed"))
- c.Redirect(setting.AppSubURL + "/" + newOwner + "/" + repo.Name)
-
- case "delete":
- if !c.Repo.IsOwner() {
- c.NotFound()
- return
- }
- if repo.Name != f.RepoName {
- c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil)
- return
- }
-
- if c.Repo.Owner.IsOrganization() && !c.User.IsAdmin {
- if !c.Repo.Owner.IsOwnedBy(c.User.ID) {
- c.NotFound()
- return
- }
- }
-
- if err := models.DeleteRepository(c.Repo.Owner.ID, repo.ID); err != nil {
- c.ServerError("DeleteRepository", err)
- return
- }
- log.Trace("Repository deleted: %s/%s", c.Repo.Owner.Name, repo.Name)
-
- c.Flash.Success(c.Tr("repo.settings.deletion_success"))
- c.Redirect(c.Repo.Owner.DashboardLink())
-
- case "delete-wiki":
- if !c.Repo.IsOwner() {
- c.NotFound()
- return
- }
- if repo.Name != f.RepoName {
- c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil)
- return
- }
-
- if c.Repo.Owner.IsOrganization() && !c.User.IsAdmin {
- if !c.Repo.Owner.IsOwnedBy(c.User.ID) {
- c.NotFound()
- return
- }
- }
-
- repo.DeleteWiki()
- log.Trace("Repository wiki deleted: %s/%s", c.Repo.Owner.Name, repo.Name)
-
- repo.EnableWiki = false
- if err := models.UpdateRepository(repo, false); err != nil {
- c.ServerError("UpdateRepository", err)
- return
- }
-
- c.Flash.Success(c.Tr("repo.settings.wiki_deletion_success"))
- c.Redirect(c.Repo.RepoLink + "/settings")
-
- default:
- c.NotFound()
- }
-}
-
-func SettingsAvatar(c *context.Context) {
- c.Title("settings.avatar")
- c.PageIs("SettingsAvatar")
- c.Success(SETTINGS_REPO_AVATAR)
-}
-
-func SettingsAvatarPost(c *context.Context, f form.Avatar) {
- f.Source = form.AVATAR_LOCAL
- if err := UpdateAvatarSetting(c, f, c.Repo.Repository); err != nil {
- c.Flash.Error(err.Error())
- } else {
- c.Flash.Success(c.Tr("settings.update_avatar_success"))
- }
- c.SubURLRedirect(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")
-}
-
-// FIXME: limit upload size
-func UpdateAvatarSetting(c *context.Context, f form.Avatar, ctxRepo *models.Repository) error {
- ctxRepo.UseCustomAvatar = true
- if f.Avatar != nil {
- r, err := f.Avatar.Open()
- if err != nil {
- return fmt.Errorf("open avatar reader: %v", err)
- }
- defer r.Close()
-
- data, err := ioutil.ReadAll(r)
- if err != nil {
- return fmt.Errorf("read avatar content: %v", err)
- }
- if !tool.IsImageFile(data) {
- return errors.New(c.Tr("settings.uploaded_avatar_not_a_image"))
- }
- if err = ctxRepo.UploadAvatar(data); err != nil {
- return fmt.Errorf("upload avatar: %v", err)
- }
- } else {
- // No avatar is uploaded and reset setting back.
- if !com.IsFile(ctxRepo.CustomAvatarPath()) {
- ctxRepo.UseCustomAvatar = false
- }
- }
-
- if err := models.UpdateRepository(ctxRepo, false); err != nil {
- return fmt.Errorf("update repository: %v", err)
- }
-
- return nil
-}
-
-func SettingsCollaboration(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.settings")
- c.Data["PageIsSettingsCollaboration"] = true
-
- users, err := c.Repo.Repository.GetCollaborators()
- if err != nil {
- c.Handle(500, "GetCollaborators", err)
- return
- }
- c.Data["Collaborators"] = users
-
- c.HTML(200, SETTINGS_COLLABORATION)
-}
-
-func SettingsCollaborationPost(c *context.Context) {
- name := strings.ToLower(c.Query("collaborator"))
- if len(name) == 0 || c.Repo.Owner.LowerName == name {
- c.Redirect(setting.AppSubURL + c.Req.URL.Path)
- return
- }
-
- u, err := models.GetUserByName(name)
- if err != nil {
- if errors.IsUserNotExist(err) {
- c.Flash.Error(c.Tr("form.user_not_exist"))
- c.Redirect(setting.AppSubURL + c.Req.URL.Path)
- } else {
- c.Handle(500, "GetUserByName", err)
- }
- return
- }
-
- // Organization is not allowed to be added as a collaborator
- if u.IsOrganization() {
- c.Flash.Error(c.Tr("repo.settings.org_not_allowed_to_be_collaborator"))
- c.Redirect(setting.AppSubURL + c.Req.URL.Path)
- return
- }
-
- if err = c.Repo.Repository.AddCollaborator(u); err != nil {
- c.Handle(500, "AddCollaborator", err)
- return
- }
-
- if setting.Service.EnableNotifyMail {
- mailer.SendCollaboratorMail(models.NewMailerUser(u), models.NewMailerUser(c.User), models.NewMailerRepo(c.Repo.Repository))
- }
-
- c.Flash.Success(c.Tr("repo.settings.add_collaborator_success"))
- c.Redirect(setting.AppSubURL + c.Req.URL.Path)
-}
-
-func ChangeCollaborationAccessMode(c *context.Context) {
- if err := c.Repo.Repository.ChangeCollaborationAccessMode(
- c.QueryInt64("uid"),
- models.AccessMode(c.QueryInt("mode"))); err != nil {
- log.Error(2, "ChangeCollaborationAccessMode: %v", err)
- return
- }
-
- c.Status(204)
-}
-
-func DeleteCollaboration(c *context.Context) {
- if err := c.Repo.Repository.DeleteCollaboration(c.QueryInt64("id")); err != nil {
- c.Flash.Error("DeleteCollaboration: " + err.Error())
- } else {
- c.Flash.Success(c.Tr("repo.settings.remove_collaborator_success"))
- }
-
- c.JSON(200, map[string]interface{}{
- "redirect": c.Repo.RepoLink + "/settings/collaboration",
- })
-}
-
-func SettingsBranches(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.settings.branches")
- c.Data["PageIsSettingsBranches"] = true
-
- if c.Repo.Repository.IsBare {
- c.Flash.Info(c.Tr("repo.settings.branches_bare"), true)
- c.HTML(200, SETTINGS_BRANCHES)
- return
- }
-
- protectBranches, err := models.GetProtectBranchesByRepoID(c.Repo.Repository.ID)
- if err != nil {
- c.Handle(500, "GetProtectBranchesByRepoID", err)
- return
- }
-
- // Filter out deleted branches
- branches := make([]string, 0, len(protectBranches))
- for i := range protectBranches {
- if c.Repo.GitRepo.IsBranchExist(protectBranches[i].Name) {
- branches = append(branches, protectBranches[i].Name)
- }
- }
- c.Data["ProtectBranches"] = branches
-
- c.HTML(200, SETTINGS_BRANCHES)
-}
-
-func UpdateDefaultBranch(c *context.Context) {
- branch := c.Query("branch")
- if c.Repo.GitRepo.IsBranchExist(branch) &&
- c.Repo.Repository.DefaultBranch != branch {
- c.Repo.Repository.DefaultBranch = branch
- if err := c.Repo.GitRepo.SetDefaultBranch(branch); err != nil {
- if !git.IsErrUnsupportedVersion(err) {
- c.Handle(500, "SetDefaultBranch", err)
- return
- }
-
- c.Flash.Warning(c.Tr("repo.settings.update_default_branch_unsupported"))
- c.Redirect(c.Repo.RepoLink + "/settings/branches")
- return
- }
- }
-
- if err := models.UpdateRepository(c.Repo.Repository, false); err != nil {
- c.Handle(500, "UpdateRepository", err)
- return
- }
-
- c.Flash.Success(c.Tr("repo.settings.update_default_branch_success"))
- c.Redirect(c.Repo.RepoLink + "/settings/branches")
-}
-
-func SettingsProtectedBranch(c *context.Context) {
- branch := c.Params("*")
- if !c.Repo.GitRepo.IsBranchExist(branch) {
- c.NotFound()
- return
- }
-
- c.Data["Title"] = c.Tr("repo.settings.protected_branches") + " - " + branch
- c.Data["PageIsSettingsBranches"] = true
-
- protectBranch, err := models.GetProtectBranchOfRepoByName(c.Repo.Repository.ID, branch)
- if err != nil {
- if !errors.IsErrBranchNotExist(err) {
- c.Handle(500, "GetProtectBranchOfRepoByName", err)
- return
- }
-
- // No options found, create defaults.
- protectBranch = &models.ProtectBranch{
- Name: branch,
- }
- }
-
- if c.Repo.Owner.IsOrganization() {
- users, err := c.Repo.Repository.GetWriters()
- if err != nil {
- c.Handle(500, "Repo.Repository.GetPushers", err)
- return
- }
- c.Data["Users"] = users
- c.Data["whitelist_users"] = protectBranch.WhitelistUserIDs
-
- teams, err := c.Repo.Owner.TeamsHaveAccessToRepo(c.Repo.Repository.ID, models.ACCESS_MODE_WRITE)
- if err != nil {
- c.Handle(500, "Repo.Owner.TeamsHaveAccessToRepo", err)
- return
- }
- c.Data["Teams"] = teams
- c.Data["whitelist_teams"] = protectBranch.WhitelistTeamIDs
- }
-
- c.Data["Branch"] = protectBranch
- c.HTML(200, SETTINGS_PROTECTED_BRANCH)
-}
-
-func SettingsProtectedBranchPost(c *context.Context, f form.ProtectBranch) {
- branch := c.Params("*")
- if !c.Repo.GitRepo.IsBranchExist(branch) {
- c.NotFound()
- return
- }
-
- protectBranch, err := models.GetProtectBranchOfRepoByName(c.Repo.Repository.ID, branch)
- if err != nil {
- if !errors.IsErrBranchNotExist(err) {
- c.Handle(500, "GetProtectBranchOfRepoByName", err)
- return
- }
-
- // No options found, create defaults.
- protectBranch = &models.ProtectBranch{
- RepoID: c.Repo.Repository.ID,
- Name: branch,
- }
- }
-
- protectBranch.Protected = f.Protected
- protectBranch.RequirePullRequest = f.RequirePullRequest
- protectBranch.EnableWhitelist = f.EnableWhitelist
- if c.Repo.Owner.IsOrganization() {
- err = models.UpdateOrgProtectBranch(c.Repo.Repository, protectBranch, f.WhitelistUsers, f.WhitelistTeams)
- } else {
- err = models.UpdateProtectBranch(protectBranch)
- }
- if err != nil {
- c.Handle(500, "UpdateOrgProtectBranch/UpdateProtectBranch", err)
- return
- }
-
- c.Flash.Success(c.Tr("repo.settings.update_protect_branch_success"))
- c.Redirect(fmt.Sprintf("%s/settings/branches/%s", c.Repo.RepoLink, branch))
-}
-
-func SettingsGitHooks(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.settings.githooks")
- c.Data["PageIsSettingsGitHooks"] = true
-
- hooks, err := c.Repo.GitRepo.Hooks()
- if err != nil {
- c.Handle(500, "Hooks", err)
- return
- }
- c.Data["Hooks"] = hooks
-
- c.HTML(200, SETTINGS_GITHOOKS)
-}
-
-func SettingsGitHooksEdit(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.settings.githooks")
- c.Data["PageIsSettingsGitHooks"] = true
- c.Data["RequireSimpleMDE"] = true
-
- name := c.Params(":name")
- hook, err := c.Repo.GitRepo.GetHook(name)
- if err != nil {
- if err == git.ErrNotValidHook {
- c.Handle(404, "GetHook", err)
- } else {
- c.Handle(500, "GetHook", err)
- }
- return
- }
- c.Data["Hook"] = hook
- c.HTML(200, SETTINGS_GITHOOK_EDIT)
-}
-
-func SettingsGitHooksEditPost(c *context.Context) {
- name := c.Params(":name")
- hook, err := c.Repo.GitRepo.GetHook(name)
- if err != nil {
- if err == git.ErrNotValidHook {
- c.Handle(404, "GetHook", err)
- } else {
- c.Handle(500, "GetHook", err)
- }
- return
- }
- hook.Content = c.Query("content")
- if err = hook.Update(); err != nil {
- c.Handle(500, "hook.Update", err)
- return
- }
- c.Redirect(c.Data["Link"].(string))
-}
-
-func SettingsDeployKeys(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.settings.deploy_keys")
- c.Data["PageIsSettingsKeys"] = true
-
- keys, err := models.ListDeployKeys(c.Repo.Repository.ID)
- if err != nil {
- c.Handle(500, "ListDeployKeys", err)
- return
- }
- c.Data["Deploykeys"] = keys
-
- c.HTML(200, SETTINGS_DEPLOY_KEYS)
-}
-
-func SettingsDeployKeysPost(c *context.Context, f form.AddSSHKey) {
- c.Data["Title"] = c.Tr("repo.settings.deploy_keys")
- c.Data["PageIsSettingsKeys"] = true
-
- keys, err := models.ListDeployKeys(c.Repo.Repository.ID)
- if err != nil {
- c.Handle(500, "ListDeployKeys", err)
- return
- }
- c.Data["Deploykeys"] = keys
-
- if c.HasError() {
- c.HTML(200, SETTINGS_DEPLOY_KEYS)
- return
- }
-
- content, err := models.CheckPublicKeyString(f.Content)
- if err != nil {
- if models.IsErrKeyUnableVerify(err) {
- c.Flash.Info(c.Tr("form.unable_verify_ssh_key"))
- } else {
- c.Data["HasError"] = true
- c.Data["Err_Content"] = true
- c.Flash.Error(c.Tr("form.invalid_ssh_key", err.Error()))
- c.Redirect(c.Repo.RepoLink + "/settings/keys")
- return
- }
- }
-
- key, err := models.AddDeployKey(c.Repo.Repository.ID, f.Title, content)
- if err != nil {
- c.Data["HasError"] = true
- switch {
- case models.IsErrKeyAlreadyExist(err):
- c.Data["Err_Content"] = true
- c.RenderWithErr(c.Tr("repo.settings.key_been_used"), SETTINGS_DEPLOY_KEYS, &f)
- case models.IsErrKeyNameAlreadyUsed(err):
- c.Data["Err_Title"] = true
- c.RenderWithErr(c.Tr("repo.settings.key_name_used"), SETTINGS_DEPLOY_KEYS, &f)
- default:
- c.Handle(500, "AddDeployKey", err)
- }
- return
- }
-
- log.Trace("Deploy key added: %d", c.Repo.Repository.ID)
- c.Flash.Success(c.Tr("repo.settings.add_key_success", key.Name))
- c.Redirect(c.Repo.RepoLink + "/settings/keys")
-}
-
-func DeleteDeployKey(c *context.Context) {
- if err := models.DeleteDeployKey(c.User, c.QueryInt64("id")); err != nil {
- c.Flash.Error("DeleteDeployKey: " + err.Error())
- } else {
- c.Flash.Success(c.Tr("repo.settings.deploy_key_deletion_success"))
- }
-
- c.JSON(200, map[string]interface{}{
- "redirect": c.Repo.RepoLink + "/settings/keys",
- })
-}
diff --git a/routes/repo/view.go b/routes/repo/view.go
deleted file mode 100644
index b6464e44..00000000
--- a/routes/repo/view.go
+++ /dev/null
@@ -1,371 +0,0 @@
-// Copyright 2014 The Gogs Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package repo
-
-import (
- "bytes"
- "fmt"
- gotemplate "html/template"
- "io/ioutil"
- "path"
- "strings"
-
- "github.com/unknwon/paginater"
- log "gopkg.in/clog.v1"
-
- "github.com/gogs/git-module"
-
- "gogs.io/gogs/models"
- "gogs.io/gogs/pkg/context"
- "gogs.io/gogs/pkg/markup"
- "gogs.io/gogs/pkg/setting"
- "gogs.io/gogs/pkg/template"
- "gogs.io/gogs/pkg/template/highlight"
- "gogs.io/gogs/pkg/tool"
-)
-
-const (
- BARE = "repo/bare"
- HOME = "repo/home"
- WATCHERS = "repo/watchers"
- FORKS = "repo/forks"
-)
-
-func renderDirectory(c *context.Context, treeLink string) {
- tree, err := c.Repo.Commit.SubTree(c.Repo.TreePath)
- if err != nil {
- c.NotFoundOrServerError("Repo.Commit.SubTree", git.IsErrNotExist, err)
- return
- }
-
- entries, err := tree.ListEntries()
- if err != nil {
- c.ServerError("ListEntries", err)
- return
- }
- entries.Sort()
-
- c.Data["Files"], err = entries.GetCommitsInfoWithCustomConcurrency(c.Repo.Commit, c.Repo.TreePath, setting.Repository.CommitsFetchConcurrency)
- if err != nil {
- c.ServerError("GetCommitsInfoWithCustomConcurrency", err)
- return
- }
-
- var readmeFile *git.Blob
- for _, entry := range entries {
- if entry.IsDir() || !markup.IsReadmeFile(entry.Name()) {
- continue
- }
-
- // TODO: collect all possible README files and show with priority.
- readmeFile = entry.Blob()
- break
- }
-
- if readmeFile != nil {
- c.Data["RawFileLink"] = ""
- c.Data["ReadmeInList"] = true
- c.Data["ReadmeExist"] = true
-
- dataRc, err := readmeFile.Data()
- if err != nil {
- c.ServerError("readmeFile.Data", err)
- return
- }
-
- buf := make([]byte, 1024)
- n, _ := dataRc.Read(buf)
- buf = buf[:n]
-
- isTextFile := tool.IsTextFile(buf)
- c.Data["IsTextFile"] = isTextFile
- c.Data["FileName"] = readmeFile.Name()
- if isTextFile {
- d, _ := ioutil.ReadAll(dataRc)
- buf = append(buf, d...)
-
- switch markup.Detect(readmeFile.Name()) {
- case markup.MARKDOWN:
- c.Data["IsMarkdown"] = true
- buf = markup.Markdown(buf, treeLink, c.Repo.Repository.ComposeMetas())
- case markup.ORG_MODE:
- c.Data["IsMarkdown"] = true
- buf = markup.OrgMode(buf, treeLink, c.Repo.Repository.ComposeMetas())
- case markup.IPYTHON_NOTEBOOK:
- c.Data["IsIPythonNotebook"] = true
- c.Data["RawFileLink"] = c.Repo.RepoLink + "/raw/" + path.Join(c.Repo.BranchName, c.Repo.TreePath, readmeFile.Name())
- default:
- buf = bytes.Replace(buf, []byte("\n"), []byte(`<br>`), -1)
- }
- c.Data["FileContent"] = string(buf)
- }
- }
-
- // Show latest commit info of repository in table header,
- // or of directory if not in root directory.
- latestCommit := c.Repo.Commit
- if len(c.Repo.TreePath) > 0 {
- latestCommit, err = c.Repo.Commit.GetCommitByPath(c.Repo.TreePath)
- if err != nil {
- c.ServerError("GetCommitByPath", err)
- return
- }
- }
- c.Data["LatestCommit"] = latestCommit
- c.Data["LatestCommitUser"] = models.ValidateCommitWithEmail(latestCommit)
-
- if c.Repo.CanEnableEditor() {
- c.Data["CanAddFile"] = true
- c.Data["CanUploadFile"] = setting.Repository.Upload.Enabled
- }
-}
-
-func renderFile(c *context.Context, entry *git.TreeEntry, treeLink, rawLink string) {
- c.Data["IsViewFile"] = true
-
- blob := entry.Blob()
- dataRc, err := blob.Data()
- if err != nil {
- c.Handle(500, "Data", err)
- return
- }
-
- c.Data["FileSize"] = blob.Size()
- c.Data["FileName"] = blob.Name()
- c.Data["HighlightClass"] = highlight.FileNameToHighlightClass(blob.Name())
- c.Data["RawFileLink"] = rawLink + "/" + c.Repo.TreePath
-
- buf := make([]byte, 1024)
- n, _ := dataRc.Read(buf)
- buf = buf[:n]
-
- isTextFile := tool.IsTextFile(buf)
- c.Data["IsTextFile"] = isTextFile
-
- // Assume file is not editable first.
- if !isTextFile {
- c.Data["EditFileTooltip"] = c.Tr("repo.editor.cannot_edit_non_text_files")
- }
-
- canEnableEditor := c.Repo.CanEnableEditor()
- switch {
- case isTextFile:
- if blob.Size() >= setting.UI.MaxDisplayFileSize {
- c.Data["IsFileTooLarge"] = true
- break
- }
-
- c.Data["ReadmeExist"] = markup.IsReadmeFile(blob.Name())
-
- d, _ := ioutil.ReadAll(dataRc)
- buf = append(buf, d...)
-
- switch markup.Detect(blob.Name()) {
- case markup.MARKDOWN:
- c.Data["IsMarkdown"] = true
- c.Data["FileContent"] = string(markup.Markdown(buf, path.Dir(treeLink), c.Repo.Repository.ComposeMetas()))
- case markup.ORG_MODE:
- c.Data["IsMarkdown"] = true
- c.Data["FileContent"] = string(markup.OrgMode(buf, path.Dir(treeLink), c.Repo.Repository.ComposeMetas()))
- case markup.IPYTHON_NOTEBOOK:
- c.Data["IsIPythonNotebook"] = true
- default:
- // Building code view blocks with line number on server side.
- var fileContent string
- if err, content := template.ToUTF8WithErr(buf); err != nil {
- if err != nil {
- log.Error(4, "ToUTF8WithErr: %s", err)
- }
- fileContent = string(buf)
- } else {
- fileContent = content
- }
-
- var output bytes.Buffer
- lines := strings.Split(fileContent, "\n")
- // Remove blank line at the end of file
- if len(lines) > 0 && len(lines[len(lines)-1])==0 {
- lines = lines[:len(lines)-1]
- }
- for index, line := range lines {
- output.WriteString(fmt.Sprintf(`<li class="L%d" rel="L%d">%s</li>`, index+1, index+1, gotemplate.HTMLEscapeString(strings.TrimRight(line, "\r"))) + "\n")
- }
- c.Data["FileContent"] = gotemplate.HTML(output.String())
-
- output.Reset()
- for i := 0; i < len(lines); i++ {
- output.WriteString(fmt.Sprintf(`<span id="L%d">%d</span>`, i+1, i+1))
- }
- c.Data["LineNums"] = gotemplate.HTML(output.String())
- }
-
- if canEnableEditor {
- c.Data["CanEditFile"] = true
- c.Data["EditFileTooltip"] = c.Tr("repo.editor.edit_this_file")
- } else if !c.Repo.IsViewBranch {
- c.Data["EditFileTooltip"] = c.Tr("repo.editor.must_be_on_a_branch")
- } else if !c.Repo.IsWriter() {
- c.Data["EditFileTooltip"] = c.Tr("repo.editor.fork_before_edit")
- }
-
- case tool.IsPDFFile(buf):
- c.Data["IsPDFFile"] = true
- case tool.IsVideoFile(buf):
- c.Data["IsVideoFile"] = true
- case tool.IsImageFile(buf):
- c.Data["IsImageFile"] = true
- }
-
- if canEnableEditor {
- c.Data["CanDeleteFile"] = true
- c.Data["DeleteFileTooltip"] = c.Tr("repo.editor.delete_this_file")
- } else if !c.Repo.IsViewBranch {
- c.Data["DeleteFileTooltip"] = c.Tr("repo.editor.must_be_on_a_branch")
- } else if !c.Repo.IsWriter() {
- c.Data["DeleteFileTooltip"] = c.Tr("repo.editor.must_have_write_access")
- }
-}
-
-func setEditorconfigIfExists(c *context.Context) {
- ec, err := c.Repo.GetEditorconfig()
- if err != nil && !git.IsErrNotExist(err) {
- log.Trace("setEditorconfigIfExists.GetEditorconfig [%d]: %v", c.Repo.Repository.ID, err)
- return
- }
- c.Data["Editorconfig"] = ec
-}
-
-func Home(c *context.Context) {
- c.Data["PageIsViewFiles"] = true
-
- if c.Repo.Repository.IsBare {
- c.HTML(200, BARE)
- return
- }
-
- title := c.Repo.Repository.Owner.Name + "/" + c.Repo.Repository.Name
- if len(c.Repo.Repository.Description) > 0 {
- title += ": " + c.Repo.Repository.Description
- }
- c.Data["Title"] = title
- if c.Repo.BranchName != c.Repo.Repository.DefaultBranch {
- c.Data["Title"] = title + " @ " + c.Repo.BranchName
- }
- c.Data["RequireHighlightJS"] = true
-
- branchLink := c.Repo.RepoLink + "/src/" + c.Repo.BranchName
- treeLink := branchLink
- rawLink := c.Repo.RepoLink + "/raw/" + c.Repo.BranchName
-
- isRootDir := false
- if len(c.Repo.TreePath) > 0 {
- treeLink += "/" + c.Repo.TreePath
- } else {
- isRootDir = true
-
- // Only show Git stats panel when view root directory
- var err error
- c.Repo.CommitsCount, err = c.Repo.Commit.CommitsCount()
- if err != nil {
- c.Handle(500, "CommitsCount", err)
- return
- }
- c.Data["CommitsCount"] = c.Repo.CommitsCount
- }
- c.Data["PageIsRepoHome"] = isRootDir
-
- // Get current entry user currently looking at.
- entry, err := c.Repo.Commit.GetTreeEntryByPath(c.Repo.TreePath)
- if err != nil {
- c.NotFoundOrServerError("Repo.Commit.GetTreeEntryByPath", git.IsErrNotExist, err)
- return
- }
-
- if entry.IsDir() {
- renderDirectory(c, treeLink)
- } else {
- renderFile(c, entry, treeLink, rawLink)
- }
- if c.Written() {
- return
- }
-
- setEditorconfigIfExists(c)
- if c.Written() {
- return
- }
-
- var treeNames []string
- paths := make([]string, 0, 5)
- if len(c.Repo.TreePath) > 0 {
- treeNames = strings.Split(c.Repo.TreePath, "/")
- for i := range treeNames {
- paths = append(paths, strings.Join(treeNames[:i+1], "/"))
- }
-
- c.Data["HasParentPath"] = true
- if len(paths)-2 >= 0 {
- c.Data["ParentPath"] = "/" + paths[len(paths)-2]
- }
- }
-
- c.Data["Paths"] = paths
- c.Data["TreeLink"] = treeLink
- c.Data["TreeNames"] = treeNames
- c.Data["BranchLink"] = branchLink
- c.HTML(200, HOME)
-}
-
-func RenderUserCards(c *context.Context, total int, getter func(page int) ([]*models.User, error), tpl string) {
- page := c.QueryInt("page")
- if page <= 0 {
- page = 1
- }
- pager := paginater.New(total, models.ItemsPerPage, page, 5)
- c.Data["Page"] = pager
-
- items, err := getter(pager.Current())
- if err != nil {
- c.Handle(500, "getter", err)
- return
- }
- c.Data["Cards"] = items
-
- c.HTML(200, tpl)
-}
-
-func Watchers(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.watchers")
- c.Data["CardsTitle"] = c.Tr("repo.watchers")
- c.Data["PageIsWatchers"] = true
- RenderUserCards(c, c.Repo.Repository.NumWatches, c.Repo.Repository.GetWatchers, WATCHERS)
-}
-
-func Stars(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.stargazers")
- c.Data["CardsTitle"] = c.Tr("repo.stargazers")
- c.Data["PageIsStargazers"] = true
- RenderUserCards(c, c.Repo.Repository.NumStars, c.Repo.Repository.GetStargazers, WATCHERS)
-}
-
-func Forks(c *context.Context) {
- c.Data["Title"] = c.Tr("repos.forks")
-
- forks, err := c.Repo.Repository.GetForks()
- if err != nil {
- c.Handle(500, "GetForks", err)
- return
- }
-
- for _, fork := range forks {
- if err = fork.GetOwner(); err != nil {
- c.Handle(500, "GetOwner", err)
- return
- }
- }
- c.Data["Forks"] = forks
-
- c.HTML(200, FORKS)
-}
diff --git a/routes/repo/webhook.go b/routes/repo/webhook.go
deleted file mode 100644
index d22140af..00000000
--- a/routes/repo/webhook.go
+++ /dev/null
@@ -1,629 +0,0 @@
-// Copyright 2015 The Gogs Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package repo
-
-import (
- "fmt"
- "strings"
-
- "github.com/unknwon/com"
- "github.com/json-iterator/go"
-
- git "github.com/gogs/git-module"
- api "github.com/gogs/go-gogs-client"
-
- "gogs.io/gogs/models"
- "gogs.io/gogs/models/errors"
- "gogs.io/gogs/pkg/context"
- "gogs.io/gogs/pkg/form"
- "gogs.io/gogs/pkg/setting"
-)
-
-const (
- WEBHOOKS = "repo/settings/webhook/base"
- WEBHOOK_NEW = "repo/settings/webhook/new"
- ORG_WEBHOOK_NEW = "org/settings/webhook_new"
-)
-
-func Webhooks(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.settings.hooks")
- c.Data["PageIsSettingsHooks"] = true
- c.Data["BaseLink"] = c.Repo.RepoLink
- c.Data["Description"] = c.Tr("repo.settings.hooks_desc", "https://github.com/gogs/go-gogs-client/wiki/Repositories-Webhooks")
- c.Data["Types"] = setting.Webhook.Types
-
- ws, err := models.GetWebhooksByRepoID(c.Repo.Repository.ID)
- if err != nil {
- c.Handle(500, "GetWebhooksByRepoID", err)
- return
- }
- c.Data["Webhooks"] = ws
-
- c.HTML(200, WEBHOOKS)
-}
-
-type OrgRepoCtx struct {
- OrgID int64
- RepoID int64
- Link string
- NewTemplate string
-}
-
-// getOrgRepoCtx determines whether this is a repo context or organization context.
-func getOrgRepoCtx(c *context.Context) (*OrgRepoCtx, error) {
- if len(c.Repo.RepoLink) > 0 {
- c.Data["PageIsRepositoryContext"] = true
- return &OrgRepoCtx{
- RepoID: c.Repo.Repository.ID,
- Link: c.Repo.RepoLink,
- NewTemplate: WEBHOOK_NEW,
- }, nil
- }
-
- if len(c.Org.OrgLink) > 0 {
- c.Data["PageIsOrganizationContext"] = true
- return &OrgRepoCtx{
- OrgID: c.Org.Organization.ID,
- Link: c.Org.OrgLink,
- NewTemplate: ORG_WEBHOOK_NEW,
- }, nil
- }
-
- return nil, errors.New("Unable to set OrgRepo context")
-}
-
-func checkHookType(c *context.Context) string {
- hookType := strings.ToLower(c.Params(":type"))
- if !com.IsSliceContainsStr(setting.Webhook.Types, hookType) {
- c.Handle(404, "checkHookType", nil)
- return ""
- }
- return hookType
-}
-
-func WebhooksNew(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.settings.add_webhook")
- c.Data["PageIsSettingsHooks"] = true
- c.Data["PageIsSettingsHooksNew"] = true
- c.Data["Webhook"] = models.Webhook{HookEvent: &models.HookEvent{}}
-
- orCtx, err := getOrgRepoCtx(c)
- if err != nil {
- c.Handle(500, "getOrgRepoCtx", err)
- return
- }
-
- c.Data["HookType"] = checkHookType(c)
- if c.Written() {
- return
- }
- c.Data["BaseLink"] = orCtx.Link
-
- c.HTML(200, orCtx.NewTemplate)
-}
-
-func ParseHookEvent(f form.Webhook) *models.HookEvent {
- return &models.HookEvent{
- PushOnly: f.PushOnly(),
- SendEverything: f.SendEverything(),
- ChooseEvents: f.ChooseEvents(),
- HookEvents: models.HookEvents{
- Create: f.Create,
- Delete: f.Delete,
- Fork: f.Fork,
- Push: f.Push,
- Issues: f.Issues,
- IssueComment: f.IssueComment,
- PullRequest: f.PullRequest,
- Release: f.Release,
- },
- }
-}
-
-func WebHooksNewPost(c *context.Context, f form.NewWebhook) {
- c.Data["Title"] = c.Tr("repo.settings.add_webhook")
- c.Data["PageIsSettingsHooks"] = true
- c.Data["PageIsSettingsHooksNew"] = true
- c.Data["Webhook"] = models.Webhook{HookEvent: &models.HookEvent{}}
- c.Data["HookType"] = "gogs"
-
- orCtx, err := getOrgRepoCtx(c)
- if err != nil {
- c.Handle(500, "getOrgRepoCtx", err)
- return
- }
- c.Data["BaseLink"] = orCtx.Link
-
- if c.HasError() {
- c.HTML(200, orCtx.NewTemplate)
- return
- }
-
- contentType := models.JSON
- if models.HookContentType(f.ContentType) == models.FORM {
- contentType = models.FORM
- }
-
- w := &models.Webhook{
- RepoID: orCtx.RepoID,
- URL: f.PayloadURL,
- ContentType: contentType,
- Secret: f.Secret,
- HookEvent: ParseHookEvent(f.Webhook),
- IsActive: f.Active,
- HookTaskType: models.GOGS,
- OrgID: orCtx.OrgID,
- }
- if err := w.UpdateEvent(); err != nil {
- c.Handle(500, "UpdateEvent", err)
- return
- } else if err := models.CreateWebhook(w); err != nil {
- c.Handle(500, "CreateWebhook", err)
- return
- }
-
- c.Flash.Success(c.Tr("repo.settings.add_hook_success"))
- c.Redirect(orCtx.Link + "/settings/hooks")
-}
-
-func SlackHooksNewPost(c *context.Context, f form.NewSlackHook) {
- c.Data["Title"] = c.Tr("repo.settings")
- c.Data["PageIsSettingsHooks"] = true
- c.Data["PageIsSettingsHooksNew"] = true
- c.Data["Webhook"] = models.Webhook{HookEvent: &models.HookEvent{}}
-
- orCtx, err := getOrgRepoCtx(c)
- if err != nil {
- c.Handle(500, "getOrgRepoCtx", err)
- return
- }
-
- if c.HasError() {
- c.HTML(200, orCtx.NewTemplate)
- return
- }
-
- meta, err := jsoniter.Marshal(&models.SlackMeta{
- Channel: f.Channel,
- Username: f.Username,
- IconURL: f.IconURL,
- Color: f.Color,
- })
- if err != nil {
- c.Handle(500, "Marshal", err)
- return
- }
-
- w := &models.Webhook{
- RepoID: orCtx.RepoID,
- URL: f.PayloadURL,
- ContentType: models.JSON,
- HookEvent: ParseHookEvent(f.Webhook),
- IsActive: f.Active,
- HookTaskType: models.SLACK,
- Meta: string(meta),
- OrgID: orCtx.OrgID,
- }
- if err := w.UpdateEvent(); err != nil {
- c.Handle(500, "UpdateEvent", err)
- return
- } else if err := models.CreateWebhook(w); err != nil {
- c.Handle(500, "CreateWebhook", err)
- return
- }
-
- c.Flash.Success(c.Tr("repo.settings.add_hook_success"))
- c.Redirect(orCtx.Link + "/settings/hooks")
-}
-
-// FIXME: merge logic to Slack
-func DiscordHooksNewPost(c *context.Context, f form.NewDiscordHook) {
- c.Data["Title"] = c.Tr("repo.settings")
- c.Data["PageIsSettingsHooks"] = true
- c.Data["PageIsSettingsHooksNew"] = true
- c.Data["Webhook"] = models.Webhook{HookEvent: &models.HookEvent{}}
-
- orCtx, err := getOrgRepoCtx(c)
- if err != nil {
- c.Handle(500, "getOrgRepoCtx", err)
- return
- }
-
- if c.HasError() {
- c.HTML(200, orCtx.NewTemplate)
- return
- }
-
- meta, err := jsoniter.Marshal(&models.SlackMeta{
- Username: f.Username,
- IconURL: f.IconURL,
- Color: f.Color,
- })
- if err != nil {
- c.Handle(500, "Marshal", err)
- return
- }
-
- w := &models.Webhook{
- RepoID: orCtx.RepoID,
- URL: f.PayloadURL,
- ContentType: models.JSON,
- HookEvent: ParseHookEvent(f.Webhook),
- IsActive: f.Active,
- HookTaskType: models.DISCORD,
- Meta: string(meta),
- OrgID: orCtx.OrgID,
- }
- if err := w.UpdateEvent(); err != nil {
- c.Handle(500, "UpdateEvent", err)
- return
- } else if err := models.CreateWebhook(w); err != nil {
- c.Handle(500, "CreateWebhook", err)
- return
- }
-
- c.Flash.Success(c.Tr("repo.settings.add_hook_success"))
- c.Redirect(orCtx.Link + "/settings/hooks")
-}
-
-func DingtalkHooksNewPost(c *context.Context, f form.NewDingtalkHook) {
- c.Data["Title"] = c.Tr("repo.settings")
- c.Data["PageIsSettingsHooks"] = true
- c.Data["PageIsSettingsHooksNew"] = true
- c.Data["Webhook"] = models.Webhook{HookEvent: &models.HookEvent{}}
-
- orCtx, err := getOrgRepoCtx(c)
- if err != nil {
- c.Handle(500, "getOrgRepoCtx", err)
- return
- }
-
- if c.HasError() {
- c.HTML(200, orCtx.NewTemplate)
- return
- }
-
- w := &models.Webhook{
- RepoID: orCtx.RepoID,
- URL: f.PayloadURL,
- ContentType: models.JSON,
- HookEvent: ParseHookEvent(f.Webhook),
- IsActive: f.Active,
- HookTaskType: models.DINGTALK,
- OrgID: orCtx.OrgID,
- }
- if err := w.UpdateEvent(); err != nil {
- c.Handle(500, "UpdateEvent", err)
- return
- } else if err := models.CreateWebhook(w); err != nil {
- c.Handle(500, "CreateWebhook", err)
- return
- }
-
- c.Flash.Success(c.Tr("repo.settings.add_hook_success"))
- c.Redirect(orCtx.Link + "/settings/hooks")
-}
-
-func checkWebhook(c *context.Context) (*OrgRepoCtx, *models.Webhook) {
- c.Data["RequireHighlightJS"] = true
-
- orCtx, err := getOrgRepoCtx(c)
- if err != nil {
- c.Handle(500, "getOrgRepoCtx", err)
- return nil, nil
- }
- c.Data["BaseLink"] = orCtx.Link
-
- var w *models.Webhook
- if orCtx.RepoID > 0 {
- w, err = models.GetWebhookOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
- } else {
- w, err = models.GetWebhookByOrgID(c.Org.Organization.ID, c.ParamsInt64(":id"))
- }
- if err != nil {
- c.NotFoundOrServerError("GetWebhookOfRepoByID/GetWebhookByOrgID", errors.IsWebhookNotExist, err)
- return nil, nil
- }
-
- switch w.HookTaskType {
- case models.SLACK:
- c.Data["SlackHook"] = w.GetSlackHook()
- c.Data["HookType"] = "slack"
- case models.DISCORD:
- c.Data["SlackHook"] = w.GetSlackHook()
- c.Data["HookType"] = "discord"
- case models.DINGTALK:
- c.Data["HookType"] = "dingtalk"
- default:
- c.Data["HookType"] = "gogs"
- }
-
- c.Data["History"], err = w.History(1)
- if err != nil {
- c.Handle(500, "History", err)
- }
- return orCtx, w
-}
-
-func WebHooksEdit(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.settings.update_webhook")
- c.Data["PageIsSettingsHooks"] = true
- c.Data["PageIsSettingsHooksEdit"] = true
-
- orCtx, w := checkWebhook(c)
- if c.Written() {
- return
- }
- c.Data["Webhook"] = w
-
- c.HTML(200, orCtx.NewTemplate)
-}
-
-func WebHooksEditPost(c *context.Context, f form.NewWebhook) {
- c.Data["Title"] = c.Tr("repo.settings.update_webhook")
- c.Data["PageIsSettingsHooks"] = true
- c.Data["PageIsSettingsHooksEdit"] = true
-
- orCtx, w := checkWebhook(c)
- if c.Written() {
- return
- }
- c.Data["Webhook"] = w
-
- if c.HasError() {
- c.HTML(200, orCtx.NewTemplate)
- return
- }
-
- contentType := models.JSON
- if models.HookContentType(f.ContentType) == models.FORM {
- contentType = models.FORM
- }
-
- w.URL = f.PayloadURL
- w.ContentType = contentType
- w.Secret = f.Secret
- w.HookEvent = ParseHookEvent(f.Webhook)
- w.IsActive = f.Active
- if err := w.UpdateEvent(); err != nil {
- c.Handle(500, "UpdateEvent", err)
- return
- } else if err := models.UpdateWebhook(w); err != nil {
- c.Handle(500, "WebHooksEditPost", err)
- return
- }
-
- c.Flash.Success(c.Tr("repo.settings.update_hook_success"))
- c.Redirect(fmt.Sprintf("%s/settings/hooks/%d", orCtx.Link, w.ID))
-}
-
-func SlackHooksEditPost(c *context.Context, f form.NewSlackHook) {
- c.Data["Title"] = c.Tr("repo.settings")
- c.Data["PageIsSettingsHooks"] = true
- c.Data["PageIsSettingsHooksEdit"] = true
-
- orCtx, w := checkWebhook(c)
- if c.Written() {
- return
- }
- c.Data["Webhook"] = w
-
- if c.HasError() {
- c.HTML(200, orCtx.NewTemplate)
- return
- }
-
- meta, err := jsoniter.Marshal(&models.SlackMeta{
- Channel: f.Channel,
- Username: f.Username,
- IconURL: f.IconURL,
- Color: f.Color,
- })
- if err != nil {
- c.Handle(500, "Marshal", err)
- return
- }
-
- w.URL = f.PayloadURL
- w.Meta = string(meta)
- w.HookEvent = ParseHookEvent(f.Webhook)
- w.IsActive = f.Active
- if err := w.UpdateEvent(); err != nil {
- c.Handle(500, "UpdateEvent", err)
- return
- } else if err := models.UpdateWebhook(w); err != nil {
- c.Handle(500, "UpdateWebhook", err)
- return
- }
-
- c.Flash.Success(c.Tr("repo.settings.update_hook_success"))
- c.Redirect(fmt.Sprintf("%s/settings/hooks/%d", orCtx.Link, w.ID))
-}
-
-// FIXME: merge logic to Slack
-func DiscordHooksEditPost(c *context.Context, f form.NewDiscordHook) {
- c.Data["Title"] = c.Tr("repo.settings")
- c.Data["PageIsSettingsHooks"] = true
- c.Data["PageIsSettingsHooksEdit"] = true
-
- orCtx, w := checkWebhook(c)
- if c.Written() {
- return
- }
- c.Data["Webhook"] = w
-
- if c.HasError() {
- c.HTML(200, orCtx.NewTemplate)
- return
- }
-
- meta, err := jsoniter.Marshal(&models.SlackMeta{
- Username: f.Username,
- IconURL: f.IconURL,
- Color: f.Color,
- })
- if err != nil {
- c.Handle(500, "Marshal", err)
- return
- }
-
- w.URL = f.PayloadURL
- w.Meta = string(meta)
- w.HookEvent = ParseHookEvent(f.Webhook)
- w.IsActive = f.Active
- if err := w.UpdateEvent(); err != nil {
- c.Handle(500, "UpdateEvent", err)
- return
- } else if err := models.UpdateWebhook(w); err != nil {
- c.Handle(500, "UpdateWebhook", err)
- return
- }
-
- c.Flash.Success(c.Tr("repo.settings.update_hook_success"))
- c.Redirect(fmt.Sprintf("%s/settings/hooks/%d", orCtx.Link, w.ID))
-}
-
-func DingtalkHooksEditPost(c *context.Context, f form.NewDingtalkHook) {
- c.Data["Title"] = c.Tr("repo.settings")
- c.Data["PageIsSettingsHooks"] = true
- c.Data["PageIsSettingsHooksEdit"] = true
-
- orCtx, w := checkWebhook(c)
- if c.Written() {
- return
- }
- c.Data["Webhook"] = w
-
- if c.HasError() {
- c.HTML(200, orCtx.NewTemplate)
- return
- }
-
- w.URL = f.PayloadURL
- w.HookEvent = ParseHookEvent(f.Webhook)
- w.IsActive = f.Active
- if err := w.UpdateEvent(); err != nil {
- c.Handle(500, "UpdateEvent", err)
- return
- } else if err := models.UpdateWebhook(w); err != nil {
- c.Handle(500, "UpdateWebhook", err)
- return
- }
-
- c.Flash.Success(c.Tr("repo.settings.update_hook_success"))
- c.Redirect(fmt.Sprintf("%s/settings/hooks/%d", orCtx.Link, w.ID))
-}
-
-func TestWebhook(c *context.Context) {
- var authorUsername, committerUsername string
-
- // Grab latest commit or fake one if it's empty repository.
- commit := c.Repo.Commit
- if commit == nil {
- ghost := models.NewGhostUser()
- commit = &git.Commit{
- ID: git.MustIDFromString(git.EMPTY_SHA),
- Author: ghost.NewGitSig(),
- Committer: ghost.NewGitSig(),
- CommitMessage: "This is a fake commit",
- }
- authorUsername = ghost.Name
- committerUsername = ghost.Name
- } else {
- // Try to match email with a real user.
- author, err := models.GetUserByEmail(commit.Author.Email)
- if err == nil {
- authorUsername = author.Name
- } else if !errors.IsUserNotExist(err) {
- c.Handle(500, "GetUserByEmail.(author)", err)
- return
- }
-
- committer, err := models.GetUserByEmail(commit.Committer.Email)
- if err == nil {
- committerUsername = committer.Name
- } else if !errors.IsUserNotExist(err) {
- c.Handle(500, "GetUserByEmail.(committer)", err)
- return
- }
- }
-
- fileStatus, err := commit.FileStatus()
- if err != nil {
- c.Handle(500, "FileStatus", err)
- return
- }
-
- apiUser := c.User.APIFormat()
- p := &api.PushPayload{
- Ref: git.BRANCH_PREFIX + c.Repo.Repository.DefaultBranch,
- Before: commit.ID.String(),
- After: commit.ID.String(),
- Commits: []*api.PayloadCommit{
- {
- ID: commit.ID.String(),
- Message: commit.Message(),
- URL: c.Repo.Repository.HTMLURL() + "/commit/" + commit.ID.String(),
- Author: &api.PayloadUser{
- Name: commit.Author.Name,
- Email: commit.Author.Email,
- UserName: authorUsername,
- },
- Committer: &api.PayloadUser{
- Name: commit.Committer.Name,
- Email: commit.Committer.Email,
- UserName: committerUsername,
- },
- Added: fileStatus.Added,
- Removed: fileStatus.Removed,
- Modified: fileStatus.Modified,
- },
- },
- Repo: c.Repo.Repository.APIFormat(nil),
- Pusher: apiUser,
- Sender: apiUser,
- }
- if err := models.TestWebhook(c.Repo.Repository, models.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)
- }
-}
-
-func RedeliveryWebhook(c *context.Context) {
- webhook, err := models.GetWebhookOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
- if err != nil {
- c.NotFoundOrServerError("GetWebhookOfRepoByID/GetWebhookByOrgID", errors.IsWebhookNotExist, err)
- return
- }
-
- hookTask, err := models.GetHookTaskOfWebhookByUUID(webhook.ID, c.Query("uuid"))
- if err != nil {
- c.NotFoundOrServerError("GetHookTaskOfWebhookByUUID/GetWebhookByOrgID", errors.IsHookTaskNotExist, err)
- return
- }
-
- hookTask.IsDelivered = false
- if err = models.UpdateHookTask(hookTask); err != nil {
- c.Handle(500, "UpdateHookTask", err)
- } else {
- go models.HookQueue.Add(c.Repo.Repository.ID)
- c.Flash.Info(c.Tr("repo.settings.webhook.redelivery_success", hookTask.UUID))
- c.Status(200)
- }
-}
-
-func DeleteWebhook(c *context.Context) {
- if err := models.DeleteWebhookOfRepoByID(c.Repo.Repository.ID, c.QueryInt64("id")); err != nil {
- c.Flash.Error("DeleteWebhookByRepoID: " + err.Error())
- } else {
- c.Flash.Success(c.Tr("repo.settings.webhook_deletion_success"))
- }
-
- c.JSON(200, map[string]interface{}{
- "redirect": c.Repo.RepoLink + "/settings/hooks",
- })
-}
diff --git a/routes/repo/wiki.go b/routes/repo/wiki.go
deleted file mode 100644
index 29979343..00000000
--- a/routes/repo/wiki.go
+++ /dev/null
@@ -1,274 +0,0 @@
-// Copyright 2015 The Gogs Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package repo
-
-import (
- "io/ioutil"
- "strings"
- "time"
-
- "github.com/gogs/git-module"
-
- "gogs.io/gogs/models"
- "gogs.io/gogs/pkg/context"
- "gogs.io/gogs/pkg/form"
- "gogs.io/gogs/pkg/markup"
-)
-
-const (
- WIKI_START = "repo/wiki/start"
- WIKI_VIEW = "repo/wiki/view"
- WIKI_NEW = "repo/wiki/new"
- WIKI_PAGES = "repo/wiki/pages"
-)
-
-func MustEnableWiki(c *context.Context) {
- if !c.Repo.Repository.EnableWiki {
- c.Handle(404, "MustEnableWiki", nil)
- return
- }
-
- if c.Repo.Repository.EnableExternalWiki {
- c.Redirect(c.Repo.Repository.ExternalWikiURL)
- return
- }
-}
-
-type PageMeta struct {
- Name string
- URL string
- Updated time.Time
-}
-
-func renderWikiPage(c *context.Context, isViewPage bool) (*git.Repository, string) {
- wikiRepo, err := git.OpenRepository(c.Repo.Repository.WikiPath())
- if err != nil {
- c.Handle(500, "OpenRepository", err)
- return nil, ""
- }
- commit, err := wikiRepo.GetBranchCommit("master")
- if err != nil {
- c.Handle(500, "GetBranchCommit", err)
- return nil, ""
- }
-
- // Get page list.
- if isViewPage {
- entries, err := commit.ListEntries()
- if err != nil {
- c.Handle(500, "ListEntries", err)
- return nil, ""
- }
- pages := make([]PageMeta, 0, len(entries))
- for i := range entries {
- if entries[i].Type == git.OBJECT_BLOB && strings.HasSuffix(entries[i].Name(), ".md") {
- name := strings.TrimSuffix(entries[i].Name(), ".md")
- pages = append(pages, PageMeta{
- Name: name,
- URL: models.ToWikiPageURL(name),
- })
- }
- }
- c.Data["Pages"] = pages
- }
-
- pageURL := c.Params(":page")
- if len(pageURL) == 0 {
- pageURL = "Home"
- }
- c.Data["PageURL"] = pageURL
-
- pageName := models.ToWikiPageName(pageURL)
- c.Data["old_title"] = pageName
- c.Data["Title"] = pageName
- c.Data["title"] = pageName
- c.Data["RequireHighlightJS"] = true
-
- blob, err := commit.GetBlobByPath(pageName + ".md")
- if err != nil {
- if git.IsErrNotExist(err) {
- c.Redirect(c.Repo.RepoLink + "/wiki/_pages")
- } else {
- c.Handle(500, "GetBlobByPath", err)
- }
- return nil, ""
- }
- r, err := blob.Data()
- if err != nil {
- c.Handle(500, "Data", err)
- return nil, ""
- }
- data, err := ioutil.ReadAll(r)
- if err != nil {
- c.Handle(500, "ReadAll", err)
- return nil, ""
- }
- if isViewPage {
- c.Data["content"] = string(markup.Markdown(data, c.Repo.RepoLink, c.Repo.Repository.ComposeMetas()))
- } else {
- c.Data["content"] = string(data)
- }
-
- return wikiRepo, pageName
-}
-
-func Wiki(c *context.Context) {
- c.Data["PageIsWiki"] = true
-
- if !c.Repo.Repository.HasWiki() {
- c.Data["Title"] = c.Tr("repo.wiki")
- c.HTML(200, WIKI_START)
- return
- }
-
- wikiRepo, pageName := renderWikiPage(c, true)
- if c.Written() {
- return
- }
-
- // Get last change information.
- lastCommit, err := wikiRepo.GetCommitByPath(pageName + ".md")
- if err != nil {
- c.Handle(500, "GetCommitByPath", err)
- return
- }
- c.Data["Author"] = lastCommit.Author
-
- c.HTML(200, WIKI_VIEW)
-}
-
-func WikiPages(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.wiki.pages")
- c.Data["PageIsWiki"] = true
-
- if !c.Repo.Repository.HasWiki() {
- c.Redirect(c.Repo.RepoLink + "/wiki")
- return
- }
-
- wikiRepo, err := git.OpenRepository(c.Repo.Repository.WikiPath())
- if err != nil {
- c.Handle(500, "OpenRepository", err)
- return
- }
- commit, err := wikiRepo.GetBranchCommit("master")
- if err != nil {
- c.Handle(500, "GetBranchCommit", err)
- return
- }
-
- entries, err := commit.ListEntries()
- if err != nil {
- c.Handle(500, "ListEntries", err)
- return
- }
- pages := make([]PageMeta, 0, len(entries))
- for i := range entries {
- if entries[i].Type == git.OBJECT_BLOB && strings.HasSuffix(entries[i].Name(), ".md") {
- commit, err := wikiRepo.GetCommitByPath(entries[i].Name())
- if err != nil {
- c.ServerError("GetCommitByPath", err)
- return
- }
- name := strings.TrimSuffix(entries[i].Name(), ".md")
- pages = append(pages, PageMeta{
- Name: name,
- URL: models.ToWikiPageURL(name),
- Updated: commit.Author.When,
- })
- }
- }
- c.Data["Pages"] = pages
-
- c.HTML(200, WIKI_PAGES)
-}
-
-func NewWiki(c *context.Context) {
- c.Data["Title"] = c.Tr("repo.wiki.new_page")
- c.Data["PageIsWiki"] = true
- c.Data["RequireSimpleMDE"] = true
-
- if !c.Repo.Repository.HasWiki() {
- c.Data["title"] = "Home"
- }
-
- c.HTML(200, WIKI_NEW)
-}
-
-func NewWikiPost(c *context.Context, f form.NewWiki) {
- c.Data["Title"] = c.Tr("repo.wiki.new_page")
- c.Data["PageIsWiki"] = true
- c.Data["RequireSimpleMDE"] = true
-
- if c.HasError() {
- c.HTML(200, WIKI_NEW)
- return
- }
-
- if err := c.Repo.Repository.AddWikiPage(c.User, f.Title, f.Content, f.Message); err != nil {
- if models.IsErrWikiAlreadyExist(err) {
- c.Data["Err_Title"] = true
- c.RenderWithErr(c.Tr("repo.wiki.page_already_exists"), WIKI_NEW, &f)
- } else {
- c.Handle(500, "AddWikiPage", err)
- }
- return
- }
-
- c.Redirect(c.Repo.RepoLink + "/wiki/" + models.ToWikiPageURL(models.ToWikiPageName(f.Title)))
-}
-
-func EditWiki(c *context.Context) {
- c.Data["PageIsWiki"] = true
- c.Data["PageIsWikiEdit"] = true
- c.Data["RequireSimpleMDE"] = true
-
- if !c.Repo.Repository.HasWiki() {
- c.Redirect(c.Repo.RepoLink + "/wiki")
- return
- }
-
- renderWikiPage(c, false)
- if c.Written() {
- return
- }
-
- c.HTML(200, WIKI_NEW)
-}
-
-func EditWikiPost(c *context.Context, f form.NewWiki) {
- c.Data["Title"] = c.Tr("repo.wiki.new_page")
- c.Data["PageIsWiki"] = true
- c.Data["RequireSimpleMDE"] = true
-
- if c.HasError() {
- c.HTML(200, WIKI_NEW)
- return
- }
-
- if err := c.Repo.Repository.EditWikiPage(c.User, f.OldTitle, f.Title, f.Content, f.Message); err != nil {
- c.Handle(500, "EditWikiPage", err)
- return
- }
-
- c.Redirect(c.Repo.RepoLink + "/wiki/" + models.ToWikiPageURL(models.ToWikiPageName(f.Title)))
-}
-
-func DeleteWikiPagePost(c *context.Context) {
- pageURL := c.Params(":page")
- if len(pageURL) == 0 {
- pageURL = "Home"
- }
-
- pageName := models.ToWikiPageName(pageURL)
- if err := c.Repo.Repository.DeleteWikiPage(c.User, pageName); err != nil {
- c.Handle(500, "DeleteWikiPage", err)
- return
- }
-
- c.JSON(200, map[string]interface{}{
- "redirect": c.Repo.RepoLink + "/wiki/",
- })
-}