mirror of https://github.com/gogs/gogs.git
api: overhaul `/repos/owner/repos/contents` (#5980)
* Fix import path renaming * api: overhaul /repos/owner/repos/contentspull/5981/head
parent
2430612ad4
commit
880d0ec19f
|
@ -39,7 +39,7 @@ func (c *APIContext) Error(status int, title string, obj interface{}) {
|
|||
}
|
||||
|
||||
if status == http.StatusInternalServerError {
|
||||
log.Error("%s: %s", title, message)
|
||||
log.ErrorDepth(5, "%s: %s", title, message)
|
||||
}
|
||||
|
||||
c.JSON(status, map[string]string{
|
||||
|
@ -63,6 +63,11 @@ func (c *APIContext) ServerError(title string, err error) {
|
|||
c.Error(http.StatusInternalServerError, title, err)
|
||||
}
|
||||
|
||||
// Errorf renders the 500 response with formatted message.
|
||||
func (c *APIContext) Errorf(err error, format string, args ...interface{}) {
|
||||
c.Error(http.StatusInternalServerError, fmt.Sprintf(format, args...), err)
|
||||
}
|
||||
|
||||
// NotFoundOrServerError use error check function to determine if the error
|
||||
// is about not found. It responses with 404 status code for not found error,
|
||||
// or error context description for logging purpose of 500 server error.
|
||||
|
|
|
@ -17,3 +17,8 @@ func IsErrRevisionNotExist(err error) bool {
|
|||
func IsErrNoMergeBase(err error) bool {
|
||||
return err == git.ErrNoMergeBase
|
||||
}
|
||||
|
||||
// IsErrSubmoduleNotExist returns true if the error is git.ErrSubmoduleNotExist.
|
||||
func IsErrSubmoduleNotExist(err error) bool {
|
||||
return err == git.ErrSubmoduleNotExist
|
||||
}
|
||||
|
|
|
@ -5,11 +5,6 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
admin2 "gogs.io/gogs/internal/route/api/v1/admin"
|
||||
misc2 "gogs.io/gogs/internal/route/api/v1/misc"
|
||||
org2 "gogs.io/gogs/internal/route/api/v1/org"
|
||||
repo2 "gogs.io/gogs/internal/route/api/v1/repo"
|
||||
user2 "gogs.io/gogs/internal/route/api/v1/user"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
|
@ -22,6 +17,11 @@ import (
|
|||
"gogs.io/gogs/internal/db"
|
||||
"gogs.io/gogs/internal/db/errors"
|
||||
"gogs.io/gogs/internal/form"
|
||||
"gogs.io/gogs/internal/route/api/v1/admin"
|
||||
"gogs.io/gogs/internal/route/api/v1/misc"
|
||||
"gogs.io/gogs/internal/route/api/v1/org"
|
||||
"gogs.io/gogs/internal/route/api/v1/repo"
|
||||
"gogs.io/gogs/internal/route/api/v1/user"
|
||||
)
|
||||
|
||||
// repoAssignment extracts information from URL parameters to retrieve the repository,
|
||||
|
@ -176,229 +176,229 @@ func RegisterRoutes(m *macaron.Macaron) {
|
|||
m.Options("/*", func() {})
|
||||
|
||||
// Miscellaneous
|
||||
m.Post("/markdown", bind(api.MarkdownOption{}), misc2.Markdown)
|
||||
m.Post("/markdown/raw", misc2.MarkdownRaw)
|
||||
m.Post("/markdown", bind(api.MarkdownOption{}), misc.Markdown)
|
||||
m.Post("/markdown/raw", misc.MarkdownRaw)
|
||||
|
||||
// Users
|
||||
m.Group("/users", func() {
|
||||
m.Get("/search", user2.Search)
|
||||
m.Get("/search", user.Search)
|
||||
|
||||
m.Group("/:username", func() {
|
||||
m.Get("", user2.GetInfo)
|
||||
m.Get("", user.GetInfo)
|
||||
|
||||
m.Group("/tokens", func() {
|
||||
m.Combo("").
|
||||
Get(user2.ListAccessTokens).
|
||||
Post(bind(api.CreateAccessTokenOption{}), user2.CreateAccessToken)
|
||||
Get(user.ListAccessTokens).
|
||||
Post(bind(api.CreateAccessTokenOption{}), user.CreateAccessToken)
|
||||
}, reqBasicAuth())
|
||||
})
|
||||
})
|
||||
|
||||
m.Group("/users", func() {
|
||||
m.Group("/:username", func() {
|
||||
m.Get("/keys", user2.ListPublicKeys)
|
||||
m.Get("/keys", user.ListPublicKeys)
|
||||
|
||||
m.Get("/followers", user2.ListFollowers)
|
||||
m.Get("/followers", user.ListFollowers)
|
||||
m.Group("/following", func() {
|
||||
m.Get("", user2.ListFollowing)
|
||||
m.Get("/:target", user2.CheckFollowing)
|
||||
m.Get("", user.ListFollowing)
|
||||
m.Get("/:target", user.CheckFollowing)
|
||||
})
|
||||
})
|
||||
}, reqToken())
|
||||
|
||||
m.Group("/user", func() {
|
||||
m.Get("", user2.GetAuthenticatedUser)
|
||||
m.Get("", user.GetAuthenticatedUser)
|
||||
m.Combo("/emails").
|
||||
Get(user2.ListEmails).
|
||||
Post(bind(api.CreateEmailOption{}), user2.AddEmail).
|
||||
Delete(bind(api.CreateEmailOption{}), user2.DeleteEmail)
|
||||
Get(user.ListEmails).
|
||||
Post(bind(api.CreateEmailOption{}), user.AddEmail).
|
||||
Delete(bind(api.CreateEmailOption{}), user.DeleteEmail)
|
||||
|
||||
m.Get("/followers", user2.ListMyFollowers)
|
||||
m.Get("/followers", user.ListMyFollowers)
|
||||
m.Group("/following", func() {
|
||||
m.Get("", user2.ListMyFollowing)
|
||||
m.Get("", user.ListMyFollowing)
|
||||
m.Combo("/:username").
|
||||
Get(user2.CheckMyFollowing).
|
||||
Put(user2.Follow).
|
||||
Delete(user2.Unfollow)
|
||||
Get(user.CheckMyFollowing).
|
||||
Put(user.Follow).
|
||||
Delete(user.Unfollow)
|
||||
})
|
||||
|
||||
m.Group("/keys", func() {
|
||||
m.Combo("").
|
||||
Get(user2.ListMyPublicKeys).
|
||||
Post(bind(api.CreateKeyOption{}), user2.CreatePublicKey)
|
||||
Get(user.ListMyPublicKeys).
|
||||
Post(bind(api.CreateKeyOption{}), user.CreatePublicKey)
|
||||
m.Combo("/:id").
|
||||
Get(user2.GetPublicKey).
|
||||
Delete(user2.DeletePublicKey)
|
||||
Get(user.GetPublicKey).
|
||||
Delete(user.DeletePublicKey)
|
||||
})
|
||||
|
||||
m.Get("/issues", repo2.ListUserIssues)
|
||||
m.Get("/issues", repo.ListUserIssues)
|
||||
}, reqToken())
|
||||
|
||||
// Repositories
|
||||
m.Get("/users/:username/repos", reqToken(), repo2.ListUserRepositories)
|
||||
m.Get("/orgs/:org/repos", reqToken(), repo2.ListOrgRepositories)
|
||||
m.Get("/users/:username/repos", reqToken(), repo.ListUserRepositories)
|
||||
m.Get("/orgs/:org/repos", reqToken(), repo.ListOrgRepositories)
|
||||
m.Combo("/user/repos", reqToken()).
|
||||
Get(repo2.ListMyRepos).
|
||||
Post(bind(api.CreateRepoOption{}), repo2.Create)
|
||||
m.Post("/org/:org/repos", reqToken(), bind(api.CreateRepoOption{}), repo2.CreateOrgRepo)
|
||||
Get(repo.ListMyRepos).
|
||||
Post(bind(api.CreateRepoOption{}), repo.Create)
|
||||
m.Post("/org/:org/repos", reqToken(), bind(api.CreateRepoOption{}), repo.CreateOrgRepo)
|
||||
|
||||
m.Group("/repos", func() {
|
||||
m.Get("/search", repo2.Search)
|
||||
m.Get("/search", repo.Search)
|
||||
|
||||
m.Get("/:username/:reponame", repoAssignment(), repo2.Get)
|
||||
m.Get("/:username/:reponame", repoAssignment(), repo.Get)
|
||||
})
|
||||
|
||||
m.Group("/repos", func() {
|
||||
m.Post("/migrate", bind(form.MigrateRepo{}), repo2.Migrate)
|
||||
m.Delete("/:username/:reponame", repoAssignment(), repo2.Delete)
|
||||
m.Post("/migrate", bind(form.MigrateRepo{}), repo.Migrate)
|
||||
m.Delete("/:username/:reponame", repoAssignment(), repo.Delete)
|
||||
|
||||
m.Group("/:username/:reponame", func() {
|
||||
m.Group("/hooks", func() {
|
||||
m.Combo("").
|
||||
Get(repo2.ListHooks).
|
||||
Post(bind(api.CreateHookOption{}), repo2.CreateHook)
|
||||
Get(repo.ListHooks).
|
||||
Post(bind(api.CreateHookOption{}), repo.CreateHook)
|
||||
m.Combo("/:id").
|
||||
Patch(bind(api.EditHookOption{}), repo2.EditHook).
|
||||
Delete(repo2.DeleteHook)
|
||||
Patch(bind(api.EditHookOption{}), repo.EditHook).
|
||||
Delete(repo.DeleteHook)
|
||||
}, reqRepoAdmin())
|
||||
|
||||
m.Group("/collaborators", func() {
|
||||
m.Get("", repo2.ListCollaborators)
|
||||
m.Get("", repo.ListCollaborators)
|
||||
m.Combo("/:collaborator").
|
||||
Get(repo2.IsCollaborator).
|
||||
Put(bind(api.AddCollaboratorOption{}), repo2.AddCollaborator).
|
||||
Delete(repo2.DeleteCollaborator)
|
||||
Get(repo.IsCollaborator).
|
||||
Put(bind(api.AddCollaboratorOption{}), repo.AddCollaborator).
|
||||
Delete(repo.DeleteCollaborator)
|
||||
}, reqRepoAdmin())
|
||||
|
||||
m.Get("/raw/*", context.RepoRef(), repo2.GetRawFile)
|
||||
m.Get("/contents/*", context.RepoRef(), repo2.GetContents)
|
||||
m.Get("/archive/*", repo2.GetArchive)
|
||||
m.Get("/raw/*", context.RepoRef(), repo.GetRawFile)
|
||||
m.Get("/contents/*", repo.GetContents)
|
||||
m.Get("/archive/*", repo.GetArchive)
|
||||
m.Group("/git/trees", func() {
|
||||
m.Get("/:sha", context.RepoRef(), repo2.GetRepoGitTree)
|
||||
m.Get("/:sha", context.RepoRef(), repo.GetRepoGitTree)
|
||||
})
|
||||
m.Get("/forks", repo2.ListForks)
|
||||
m.Get("/forks", repo.ListForks)
|
||||
m.Group("/branches", func() {
|
||||
m.Get("", repo2.ListBranches)
|
||||
m.Get("/*", repo2.GetBranch)
|
||||
m.Get("", repo.ListBranches)
|
||||
m.Get("/*", repo.GetBranch)
|
||||
})
|
||||
m.Group("/commits", func() {
|
||||
m.Get("/:sha", repo2.GetSingleCommit)
|
||||
m.Get("/*", repo2.GetReferenceSHA)
|
||||
m.Get("/:sha", repo.GetSingleCommit)
|
||||
m.Get("/*", repo.GetReferenceSHA)
|
||||
})
|
||||
|
||||
m.Group("/keys", func() {
|
||||
m.Combo("").
|
||||
Get(repo2.ListDeployKeys).
|
||||
Post(bind(api.CreateKeyOption{}), repo2.CreateDeployKey)
|
||||
Get(repo.ListDeployKeys).
|
||||
Post(bind(api.CreateKeyOption{}), repo.CreateDeployKey)
|
||||
m.Combo("/:id").
|
||||
Get(repo2.GetDeployKey).
|
||||
Delete(repo2.DeleteDeploykey)
|
||||
Get(repo.GetDeployKey).
|
||||
Delete(repo.DeleteDeploykey)
|
||||
}, reqRepoAdmin())
|
||||
|
||||
m.Group("/issues", func() {
|
||||
m.Combo("").
|
||||
Get(repo2.ListIssues).
|
||||
Post(bind(api.CreateIssueOption{}), repo2.CreateIssue)
|
||||
Get(repo.ListIssues).
|
||||
Post(bind(api.CreateIssueOption{}), repo.CreateIssue)
|
||||
m.Group("/comments", func() {
|
||||
m.Get("", repo2.ListRepoIssueComments)
|
||||
m.Patch("/:id", bind(api.EditIssueCommentOption{}), repo2.EditIssueComment)
|
||||
m.Get("", repo.ListRepoIssueComments)
|
||||
m.Patch("/:id", bind(api.EditIssueCommentOption{}), repo.EditIssueComment)
|
||||
})
|
||||
m.Group("/:index", func() {
|
||||
m.Combo("").
|
||||
Get(repo2.GetIssue).
|
||||
Patch(bind(api.EditIssueOption{}), repo2.EditIssue)
|
||||
Get(repo.GetIssue).
|
||||
Patch(bind(api.EditIssueOption{}), repo.EditIssue)
|
||||
|
||||
m.Group("/comments", func() {
|
||||
m.Combo("").
|
||||
Get(repo2.ListIssueComments).
|
||||
Post(bind(api.CreateIssueCommentOption{}), repo2.CreateIssueComment)
|
||||
Get(repo.ListIssueComments).
|
||||
Post(bind(api.CreateIssueCommentOption{}), repo.CreateIssueComment)
|
||||
m.Combo("/:id").
|
||||
Patch(bind(api.EditIssueCommentOption{}), repo2.EditIssueComment).
|
||||
Delete(repo2.DeleteIssueComment)
|
||||
Patch(bind(api.EditIssueCommentOption{}), repo.EditIssueComment).
|
||||
Delete(repo.DeleteIssueComment)
|
||||
})
|
||||
|
||||
m.Get("/labels", repo2.ListIssueLabels)
|
||||
m.Get("/labels", repo.ListIssueLabels)
|
||||
m.Group("/labels", func() {
|
||||
m.Combo("").
|
||||
Post(bind(api.IssueLabelsOption{}), repo2.AddIssueLabels).
|
||||
Put(bind(api.IssueLabelsOption{}), repo2.ReplaceIssueLabels).
|
||||
Delete(repo2.ClearIssueLabels)
|
||||
m.Delete("/:id", repo2.DeleteIssueLabel)
|
||||
Post(bind(api.IssueLabelsOption{}), repo.AddIssueLabels).
|
||||
Put(bind(api.IssueLabelsOption{}), repo.ReplaceIssueLabels).
|
||||
Delete(repo.ClearIssueLabels)
|
||||
m.Delete("/:id", repo.DeleteIssueLabel)
|
||||
}, reqRepoWriter())
|
||||
})
|
||||
}, mustEnableIssues)
|
||||
|
||||
m.Group("/labels", func() {
|
||||
m.Get("", repo2.ListLabels)
|
||||
m.Get("/:id", repo2.GetLabel)
|
||||
m.Get("", repo.ListLabels)
|
||||
m.Get("/:id", repo.GetLabel)
|
||||
})
|
||||
m.Group("/labels", func() {
|
||||
m.Post("", bind(api.CreateLabelOption{}), repo2.CreateLabel)
|
||||
m.Post("", bind(api.CreateLabelOption{}), repo.CreateLabel)
|
||||
m.Combo("/:id").
|
||||
Patch(bind(api.EditLabelOption{}), repo2.EditLabel).
|
||||
Delete(repo2.DeleteLabel)
|
||||
Patch(bind(api.EditLabelOption{}), repo.EditLabel).
|
||||
Delete(repo.DeleteLabel)
|
||||
}, reqRepoWriter())
|
||||
|
||||
m.Group("/milestones", func() {
|
||||
m.Get("", repo2.ListMilestones)
|
||||
m.Get("/:id", repo2.GetMilestone)
|
||||
m.Get("", repo.ListMilestones)
|
||||
m.Get("/:id", repo.GetMilestone)
|
||||
})
|
||||
m.Group("/milestones", func() {
|
||||
m.Post("", bind(api.CreateMilestoneOption{}), repo2.CreateMilestone)
|
||||
m.Post("", bind(api.CreateMilestoneOption{}), repo.CreateMilestone)
|
||||
m.Combo("/:id").
|
||||
Patch(bind(api.EditMilestoneOption{}), repo2.EditMilestone).
|
||||
Delete(repo2.DeleteMilestone)
|
||||
Patch(bind(api.EditMilestoneOption{}), repo.EditMilestone).
|
||||
Delete(repo.DeleteMilestone)
|
||||
}, reqRepoWriter())
|
||||
|
||||
m.Patch("/issue-tracker", reqRepoWriter(), bind(api.EditIssueTrackerOption{}), repo2.IssueTracker)
|
||||
m.Post("/mirror-sync", reqRepoWriter(), repo2.MirrorSync)
|
||||
m.Get("/editorconfig/:filename", context.RepoRef(), repo2.GetEditorconfig)
|
||||
m.Patch("/issue-tracker", reqRepoWriter(), bind(api.EditIssueTrackerOption{}), repo.IssueTracker)
|
||||
m.Post("/mirror-sync", reqRepoWriter(), repo.MirrorSync)
|
||||
m.Get("/editorconfig/:filename", context.RepoRef(), repo.GetEditorconfig)
|
||||
}, repoAssignment())
|
||||
}, reqToken())
|
||||
|
||||
m.Get("/issues", reqToken(), repo2.ListUserIssues)
|
||||
m.Get("/issues", reqToken(), repo.ListUserIssues)
|
||||
|
||||
// Organizations
|
||||
m.Combo("/user/orgs", reqToken()).
|
||||
Get(org2.ListMyOrgs).
|
||||
Post(bind(api.CreateOrgOption{}), org2.CreateMyOrg)
|
||||
Get(org.ListMyOrgs).
|
||||
Post(bind(api.CreateOrgOption{}), org.CreateMyOrg)
|
||||
|
||||
m.Get("/users/:username/orgs", org2.ListUserOrgs)
|
||||
m.Get("/users/:username/orgs", org.ListUserOrgs)
|
||||
m.Group("/orgs/:orgname", func() {
|
||||
m.Combo("").
|
||||
Get(org2.Get).
|
||||
Patch(bind(api.EditOrgOption{}), org2.Edit)
|
||||
m.Get("/teams", org2.ListTeams)
|
||||
Get(org.Get).
|
||||
Patch(bind(api.EditOrgOption{}), org.Edit)
|
||||
m.Get("/teams", org.ListTeams)
|
||||
}, orgAssignment(true))
|
||||
|
||||
m.Group("/admin", func() {
|
||||
m.Group("/users", func() {
|
||||
m.Post("", bind(api.CreateUserOption{}), admin2.CreateUser)
|
||||
m.Post("", bind(api.CreateUserOption{}), admin.CreateUser)
|
||||
|
||||
m.Group("/:username", func() {
|
||||
m.Combo("").
|
||||
Patch(bind(api.EditUserOption{}), admin2.EditUser).
|
||||
Delete(admin2.DeleteUser)
|
||||
m.Post("/keys", bind(api.CreateKeyOption{}), admin2.CreatePublicKey)
|
||||
m.Post("/orgs", bind(api.CreateOrgOption{}), admin2.CreateOrg)
|
||||
m.Post("/repos", bind(api.CreateRepoOption{}), admin2.CreateRepo)
|
||||
Patch(bind(api.EditUserOption{}), admin.EditUser).
|
||||
Delete(admin.DeleteUser)
|
||||
m.Post("/keys", bind(api.CreateKeyOption{}), admin.CreatePublicKey)
|
||||
m.Post("/orgs", bind(api.CreateOrgOption{}), admin.CreateOrg)
|
||||
m.Post("/repos", bind(api.CreateRepoOption{}), admin.CreateRepo)
|
||||
})
|
||||
})
|
||||
|
||||
m.Group("/orgs/:orgname", func() {
|
||||
m.Group("/teams", func() {
|
||||
m.Post("", orgAssignment(true), bind(api.CreateTeamOption{}), admin2.CreateTeam)
|
||||
m.Post("", orgAssignment(true), bind(api.CreateTeamOption{}), admin.CreateTeam)
|
||||
})
|
||||
})
|
||||
|
||||
m.Group("/teams", func() {
|
||||
m.Group("/:teamid", func() {
|
||||
m.Combo("/members/:username").
|
||||
Put(admin2.AddTeamMember).
|
||||
Delete(admin2.RemoveTeamMember)
|
||||
Put(admin.AddTeamMember).
|
||||
Delete(admin.RemoveTeamMember)
|
||||
m.Combo("/repos/:reponame").
|
||||
Put(admin2.AddTeamRepository).
|
||||
Delete(admin2.RemoveTeamRepository)
|
||||
Put(admin.AddTeamRepository).
|
||||
Delete(admin.RemoveTeamRepository)
|
||||
}, orgAssignment(false, true))
|
||||
})
|
||||
}, reqAdmin())
|
||||
|
|
|
@ -7,128 +7,141 @@ package repo
|
|||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"github.com/gogs/git-module"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/gitutil"
|
||||
)
|
||||
|
||||
type repoContent struct {
|
||||
Type string `json:"type"`
|
||||
Target string `json:"target,omitempty"`
|
||||
SubmoduleGitURL string `json:"submodule_git_url,omitempty"`
|
||||
Encoding string `json:"encoding,omitempty"`
|
||||
Size int64 `json:"size"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
Content string `json:"content,omitempty"`
|
||||
Sha string `json:"sha"`
|
||||
URL string `json:"url"`
|
||||
GitURL string `json:"git_url"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
DownloadURL string `json:"download_url"`
|
||||
Links Links `json:"_links"`
|
||||
}
|
||||
|
||||
type Links struct {
|
||||
Git string `json:"git"`
|
||||
Self string `json:"self"`
|
||||
HTML string `json:"html"`
|
||||
}
|
||||
|
||||
func GetContents(c *context.APIContext) {
|
||||
treeEntry, err := c.Repo.Commit.TreeEntry(c.Repo.TreePath)
|
||||
gitRepo, err := git.Open(c.Repo.Repository.RepoPath())
|
||||
if err != nil {
|
||||
c.ServerError("open repository", err)
|
||||
return
|
||||
}
|
||||
|
||||
ref := c.Query("ref")
|
||||
if ref == "" {
|
||||
ref = c.Repo.Repository.DefaultBranch
|
||||
}
|
||||
|
||||
commit, err := gitRepo.CatFileCommit(ref)
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("get commit", gitutil.IsErrRevisionNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
treePath := c.Params("*")
|
||||
entry, err := commit.TreeEntry(treePath)
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("get tree entry", gitutil.IsErrRevisionNotExist, err)
|
||||
return
|
||||
}
|
||||
username := c.Params(":username")
|
||||
reponame := c.Params(":reponame")
|
||||
|
||||
// TODO: figure out the best way to do this
|
||||
// :base-url/:username/:project/raw/:refs/:path
|
||||
templateDownloadURL := "%s/%s/%s/raw/%s"
|
||||
// :base-url/repos/:username/:project/contents/:path
|
||||
templateSelfLink := "%s/repos/%s/%s/contents/%s"
|
||||
// :baseurl/repos/:username/:project/git/trees/:sha
|
||||
templateGitURLLink := "%s/repos/%s/%s/trees/%s"
|
||||
// :baseurl/repos/:username/:project/tree/:sha
|
||||
templateHTMLLLink := "%s/repos/%s/%s/tree/%s"
|
||||
|
||||
gitURL := fmt.Sprintf(templateGitURLLink, c.BaseURL, username, reponame, treeEntry.ID().String())
|
||||
htmlURL := fmt.Sprintf(templateHTMLLLink, c.BaseURL, username, reponame, treeEntry.ID().String())
|
||||
selfURL := fmt.Sprintf(templateSelfLink, c.BaseURL, username, reponame, c.Repo.TreePath)
|
||||
|
||||
// TODO(unknwon): Make a treeEntryToRepoContent helper.
|
||||
contents := &repoContent{
|
||||
Size: treeEntry.Size(),
|
||||
Name: treeEntry.Name(),
|
||||
Path: c.Repo.TreePath,
|
||||
Sha: treeEntry.ID().String(),
|
||||
URL: selfURL,
|
||||
GitURL: gitURL,
|
||||
HTMLURL: htmlURL,
|
||||
DownloadURL: fmt.Sprintf(templateDownloadURL, c.BaseURL, username, reponame, c.Repo.TreePath),
|
||||
Links: Links{
|
||||
Git: gitURL,
|
||||
Self: selfURL,
|
||||
HTML: htmlURL,
|
||||
},
|
||||
type links struct {
|
||||
Git string `json:"git"`
|
||||
Self string `json:"self"`
|
||||
HTML string `json:"html"`
|
||||
}
|
||||
type repoContent struct {
|
||||
Type string `json:"type"`
|
||||
Target string `json:"target,omitempty"`
|
||||
SubmoduleGitURL string `json:"submodule_git_url,omitempty"`
|
||||
Encoding string `json:"encoding,omitempty"`
|
||||
Size int64 `json:"size"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
Content string `json:"content,omitempty"`
|
||||
Sha string `json:"sha"`
|
||||
URL string `json:"url"`
|
||||
GitURL string `json:"git_url"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
DownloadURL string `json:"download_url"`
|
||||
Links links `json:"_links"`
|
||||
}
|
||||
|
||||
// A tree entry can only be one of the following types:
|
||||
// 1. Tree (directory)
|
||||
// 2. SubModule
|
||||
// 3. SymLink
|
||||
// 4. Blob (file)
|
||||
if treeEntry.IsCommit() {
|
||||
// TODO(unknwon): submoduleURL is not set as current git-module doesn't handle it properly
|
||||
contents.Type = "submodule"
|
||||
c.JSONSuccess(contents)
|
||||
return
|
||||
toRepoContent := func(subpath string, entry *git.TreeEntry) (*repoContent, error) {
|
||||
repoURL := fmt.Sprintf("%s/repos/%s/%s", c.BaseURL, c.Params(":username"), c.Params(":reponame"))
|
||||
selfURL := fmt.Sprintf("%s/contents/%s", repoURL, subpath)
|
||||
htmlURL := fmt.Sprintf("%s/src/%s/%s", c.Repo.Repository.HTMLURL(), ref, entry.Name())
|
||||
downloadURL := fmt.Sprintf("%s/raw/%s/%s", c.Repo.Repository.HTMLURL(), ref, entry.Name())
|
||||
|
||||
} else if treeEntry.IsSymlink() {
|
||||
contents.Type = "symlink"
|
||||
blob, err := c.Repo.Commit.Blob(c.Repo.TreePath)
|
||||
if err != nil {
|
||||
c.ServerError("GetBlobByPath", err)
|
||||
return
|
||||
content := &repoContent{
|
||||
Size: entry.Size(),
|
||||
Name: entry.Name(),
|
||||
Path: subpath,
|
||||
Sha: entry.ID().String(),
|
||||
URL: selfURL,
|
||||
HTMLURL: htmlURL,
|
||||
DownloadURL: downloadURL,
|
||||
Links: links{
|
||||
Self: selfURL,
|
||||
HTML: htmlURL,
|
||||
},
|
||||
}
|
||||
p, err := blob.Bytes()
|
||||
if err != nil {
|
||||
c.ServerError("Data", err)
|
||||
return
|
||||
}
|
||||
contents.Target = string(p)
|
||||
c.JSONSuccess(contents)
|
||||
return
|
||||
|
||||
} else if treeEntry.IsBlob() {
|
||||
blob, err := c.Repo.Commit.Blob(c.Repo.TreePath)
|
||||
switch {
|
||||
case entry.IsBlob(), entry.IsExec():
|
||||
content.Type = "file"
|
||||
p, err := entry.Blob().Bytes()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get blob content")
|
||||
}
|
||||
content.Encoding = "base64"
|
||||
content.Content = base64.StdEncoding.EncodeToString(p)
|
||||
content.GitURL = fmt.Sprintf("%s/git/blobs/%s", repoURL, entry.ID().String())
|
||||
|
||||
case entry.IsTree():
|
||||
content.Type = "dir"
|
||||
content.GitURL = fmt.Sprintf("%s/git/trees/%s", repoURL, entry.ID().String())
|
||||
|
||||
case entry.IsSymlink():
|
||||
content.Type = "symlink"
|
||||
p, err := entry.Blob().Bytes()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get blob content")
|
||||
}
|
||||
content.Target = string(p)
|
||||
|
||||
case entry.IsCommit():
|
||||
content.Type = "submodule"
|
||||
mod, err := commit.Submodule(subpath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get submodule")
|
||||
}
|
||||
content.SubmoduleGitURL = mod.URL
|
||||
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
content.Links.Git = content.GitURL
|
||||
|
||||
return content, nil
|
||||
}
|
||||
|
||||
if !entry.IsTree() {
|
||||
content, err := toRepoContent(treePath, entry)
|
||||
if err != nil {
|
||||
c.ServerError("GetBlobByPath", err)
|
||||
c.Errorf(err, "convert %q to repoContent", treePath)
|
||||
return
|
||||
}
|
||||
p, err := blob.Bytes()
|
||||
if err != nil {
|
||||
c.ServerError("Data", err)
|
||||
return
|
||||
}
|
||||
contents.Content = base64.StdEncoding.EncodeToString(p)
|
||||
contents.Type = "file"
|
||||
c.JSONSuccess(contents)
|
||||
|
||||
c.JSONSuccess(content)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: treeEntry.IsExec()
|
||||
|
||||
// treeEntry is a directory
|
||||
dirTree, err := c.Repo.GitRepo.LsTree(treeEntry.ID().String())
|
||||
// The entry is a directory
|
||||
dir, err := gitRepo.LsTree(entry.ID().String())
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("get tree", gitutil.IsErrRevisionNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
entries, err := dirTree.Entries()
|
||||
entries, err := dir.Entries()
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("list entries", gitutil.IsErrRevisionNotExist, err)
|
||||
return
|
||||
|
@ -139,50 +152,16 @@ func GetContents(c *context.APIContext) {
|
|||
return
|
||||
}
|
||||
|
||||
var results = make([]*repoContent, 0, len(entries))
|
||||
contents := make([]*repoContent, 0, len(entries))
|
||||
for _, entry := range entries {
|
||||
gitURL := fmt.Sprintf(templateGitURLLink, c.BaseURL, username, reponame, entry.ID().String())
|
||||
htmlURL := fmt.Sprintf(templateHTMLLLink, c.BaseURL, username, reponame, entry.ID().String())
|
||||
selfURL := fmt.Sprintf(templateSelfLink, c.BaseURL, username, reponame, c.Repo.TreePath)
|
||||
var contentType string
|
||||
if entry.IsTree() {
|
||||
contentType = "dir"
|
||||
} else if entry.IsCommit() {
|
||||
// TODO(unknwon): submoduleURL is not set as current git-module doesn't handle it properly
|
||||
contentType = "submodule"
|
||||
} else if entry.IsSymlink() {
|
||||
contentType = "symlink"
|
||||
blob, err := c.Repo.Commit.Blob(c.Repo.TreePath)
|
||||
if err != nil {
|
||||
c.ServerError("GetBlobByPath", err)
|
||||
return
|
||||
}
|
||||
p, err := blob.Bytes()
|
||||
if err != nil {
|
||||
c.ServerError("Data", err)
|
||||
return
|
||||
}
|
||||
contents.Target = string(p)
|
||||
} else {
|
||||
contentType = "file"
|
||||
subpath := path.Join(treePath, entry.Name())
|
||||
content, err := toRepoContent(subpath, entry)
|
||||
if err != nil {
|
||||
c.Errorf(err, "convert %q to repoContent", subpath)
|
||||
return
|
||||
}
|
||||
|
||||
results = append(results, &repoContent{
|
||||
Type: contentType,
|
||||
Size: entry.Size(),
|
||||
Name: entry.Name(),
|
||||
Path: c.Repo.TreePath,
|
||||
Sha: entry.ID().String(),
|
||||
URL: selfURL,
|
||||
GitURL: gitURL,
|
||||
HTMLURL: htmlURL,
|
||||
DownloadURL: fmt.Sprintf(templateDownloadURL, c.BaseURL, username, reponame, c.Repo.TreePath),
|
||||
Links: Links{
|
||||
Git: gitURL,
|
||||
Self: selfURL,
|
||||
HTML: htmlURL,
|
||||
},
|
||||
})
|
||||
contents = append(contents, content)
|
||||
}
|
||||
c.JSONSuccess(results)
|
||||
c.JSONSuccess(contents)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue