From cf3d55fa10f9b16d0ba996f8129f50743b2cd4ad Mon Sep 17 00:00:00 2001 From: Bharat Nallan Date: Tue, 25 Feb 2020 06:19:42 -0800 Subject: api: support getting repository Git tree (#5934) (#5937) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add basic git repository tree api (#5934) This PR adds the tree api endpoint to gogs api: `GET/repos/:owner/:repo/git/trees/:tree_sha` This new api endpoint that is being added is in conformance to the GitHub REST API v3 specification. Documentation can be found here: developer.github.com/v3/git/trees/#get-a-tree For a given user, repo and sha value, this api (currently) returns a single tree using the SHA1 value for that tree. - Recursive implementation is yet to be implemented. - Creating a Tree using POST is yet to be implemented. Example curl: ``` l curl -H "Authorization: token REDACTED" http://localhost:3000/api/v1/repos/root/testrepo/git/trees/c59441ded1549b149def0d4c54594d31a7f3718f -X GET | jq . % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 940 100 940 0 0 12034 0 --:--:-- --:--:-- --:--:-- 12051 [ { "sha": "c59441ded1549b149def0d4c54594d31a7f3718f", "tree": [ { "mode": "120000", "path": "/home/bharatnc/gogs-repositories/root/testrepo.git", "sha": "472ac2361b65136b393d652de25341e2ea44f299", "size": 1077, "type": "blob", "url": "http://localhost:3000/api/v1/repos/root/testrepo/git/trees/472ac2361b65136b393d652de25341e2ea44f299" }, { "mode": "120000", "path": "/home/bharatnc/gogs-repositories/root/testrepo.git", "sha": "70fcb456d436f08462602f26df6fb7e167e7a916", "size": 12, "type": "blob", "url": "http://localhost:3000/api/v1/repos/root/testrepo/git/trees/70fcb456d436f08462602f26df6fb7e167e7a916" }, { "mode": "120000", "path": "/home/bharatnc/gogs-repositories/root/testrepo.git", "sha": "092c58d4b63df5779a4d020b1fdbb762421bbb4f", "size": 380, "type": "blob", "url": "http://localhost:3000/api/v1/repos/root/testrepo/git/trees/092c58d4b63df5779a4d020b1fdbb762421bbb4f" } ], "url": "http://localhost:3000/api/v1/repos/root/testrepo/git/trees/c59441ded1549b149def0d4c54594d31a7f3718f" } ] ``` * remove vertical space * make go.mod to be same as in master * rename structs to sound better * simplify expressions and fix error msg * Update tree.go * Update tree.go * display file name instead of repo path * Update tree.go Co-authored-by: ᴜɴᴋɴᴡᴏɴ --- internal/route/api/v1/api.go | 3 ++ internal/route/api/v1/repo/tree.go | 77 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 internal/route/api/v1/repo/tree.go (limited to 'internal') diff --git a/internal/route/api/v1/api.go b/internal/route/api/v1/api.go index 56e7bcd2..6f5ebdb5 100644 --- a/internal/route/api/v1/api.go +++ b/internal/route/api/v1/api.go @@ -272,6 +272,9 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("/raw/*", context.RepoRef(), repo2.GetRawFile) m.Get("/archive/*", repo2.GetArchive) + m.Group("/git/trees", func() { + m.Get("/:sha", context.RepoRef(), repo2.GetRepoGitTree) + }) m.Get("/forks", repo2.ListForks) m.Group("/branches", func() { m.Get("", repo2.ListBranches) diff --git a/internal/route/api/v1/repo/tree.go b/internal/route/api/v1/repo/tree.go new file mode 100644 index 00000000..c39f3acd --- /dev/null +++ b/internal/route/api/v1/repo/tree.go @@ -0,0 +1,77 @@ +package repo + +import ( + "fmt" + + "github.com/gogs/git-module" + + "gogs.io/gogs/internal/context" +) + +type repoGitTree struct { + Sha string `json:"sha"` + URL string `json:"url"` + Tree []*repoGitTreeEntry `json:"tree"` +} + +type repoGitTreeEntry struct { + Path string `json:"path"` + Mode string `json:"mode"` + Type string `json:"type"` + Size int64 `json:"size"` + Sha string `json:"sha"` + URL string `json:"url"` +} + +func GetRepoGitTree(c *context.APIContext) { + gitTree, err := c.Repo.GitRepo.GetTree(c.Params(":sha")) + if err != nil { + c.NotFoundOrServerError("GetRepoGitTree", git.IsErrNotExist, err) + return + } + entries, err := gitTree.ListEntries() + if err != nil { + c.ServerError("GetRepoGitTree", err) + return + } + + templateURL := fmt.Sprintf("%s/repos/%s/%s/git/trees", c.BaseURL, c.Params(":username"), c.Params(":reponame")) + + if len(entries) == 0 { + c.JSONSuccess(&repoGitTree{ + Sha: c.Params(":sha"), + URL: fmt.Sprintf(templateURL+"/%s", c.Params(":sha")), + }) + return + } + + children := make([]*repoGitTreeEntry, 0, len(entries)) + for _, entry := range entries { + var mode string + switch entry.Type { + case git.ObjectCommit: + mode = "160000" + case git.ObjectTree: + mode = "040000" + case git.ObjectBlob: + mode = "120000" + case git.ObjectTag: + mode = "100644" + default: + mode = "" + } + children = append(children, &repoGitTreeEntry{ + Path: entry.Name(), + Mode: mode, + Type: string(entry.Type), + Size: entry.Size(), + Sha: entry.ID.String(), + URL: fmt.Sprintf(templateURL+"/%s", entry.ID.String()), + }) + } + c.JSONSuccess(&repoGitTree{ + Sha: c.Params(":sha"), + URL: fmt.Sprintf(templateURL+"/%s", c.Params(":sha")), + Tree: children, + }) +} -- cgit v1.2.3