Browse Source

api: support getting repository Git tree (#5934) (#5937)

* 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: ᴜɴᴋɴᴡᴏɴ <u@gogs.io>
Bharat Nallan 4 năm trước cách đây
mục cha
commit
cf3d55fa10
2 tập tin đã thay đổi với 80 bổ sung0 xóa
  1. 3 0
      internal/route/api/v1/api.go
  2. 77 0
      internal/route/api/v1/repo/tree.go

+ 3 - 0
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)

+ 77 - 0
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,
+	})
+}