Chromium Code Reviews| Index: appengine/cmd/milo/git/gitiles.go |
| diff --git a/appengine/cmd/milo/git/gitiles.go b/appengine/cmd/milo/git/gitiles.go |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..b43d4af46b48508a74c2a5f4e8154ebee6ebcbad |
| --- /dev/null |
| +++ b/appengine/cmd/milo/git/gitiles.go |
| @@ -0,0 +1,103 @@ |
| +// Copyright 2016 The LUCI Authors. All rights reserved. |
| +// Use of this source code is governed under the Apache License, Version 2.0 |
| +// that can be found in the LICENSE file. |
| + |
| +package git |
| + |
| +import ( |
| + "encoding/json" |
| + "fmt" |
| + "net/url" |
| + "strings" |
| + |
| + "github.com/luci/luci-go/appengine/cmd/milo/resp" |
| + "github.com/luci/luci-go/common/transport" |
| + "golang.org/x/net/context" |
| +) |
| + |
| +type Repo struct { |
|
estaab
2016/08/04 23:21:25
docs. doesn't lint warn about this?
hinoka
2016/08/05 00:10:42
They're types not methods, so apparently not.
|
| + Server string |
| + Branch string |
| +} |
| + |
| +type Author struct { |
| + Name string `json:"name"` |
| + Email string `json:"email"` |
| + Time string `json:"time"` |
| +} |
| + |
| +type Commiter struct { |
| + Name string `json:"name"` |
| + Email string `json:"email"` |
| + Time string `json:"time"` |
| +} |
| + |
| +type Log struct { |
| + Commit string `json:"commit"` |
| + Tree string `json:"tree"` |
| + Parents []string `json:"parents"` |
| + Author Author `json:"author"` |
| + Committer Commiter `json:"committer"` |
| + Message string `json:"message"` |
| +} |
| + |
| +type Commit struct { |
| + Log []Log `json:"log"` |
| + Next string `json:"next"` |
| +} |
| + |
| +func fixURL(repoURL, treeish string) (string, error) { |
| + u, err := url.Parse(repoURL) |
| + if err != nil { |
| + return "", err |
| + } |
| + if u.Scheme != "https" { |
| + return "", fmt.Errorf("%s should start with https://", repoURL) |
| + } |
| + if !strings.HasSuffix(u.Host, "googlesource.com") { |
| + return "", fmt.Errorf("Only googlesource.com repos supported") |
| + } |
| + URL := fmt.Sprintf("%s/+log/%s?format=JSON", repoURL, treeish) |
| + // Use the authenticated URL |
| + u.Path = "a/" + u.Path |
|
estaab
2016/08/04 23:21:25
u isn't used after this line?
hinoka
2016/08/05 00:10:42
Good catch. Fixed.
|
| + return URL, nil |
| +} |
| + |
| +func GetCommits(c context.Context, repoURL, treeish string) ([]resp.Commit, error) { |
|
estaab
2016/08/04 23:21:25
docs
hinoka
2016/08/05 00:10:42
Done.
|
| + URL, err := fixURL(repoURL, treeish) |
| + if err != nil { |
| + return nil, err |
| + } |
| + client := transport.GetClient(c) |
| + r, err := client.Get(URL) |
| + if err != nil { |
| + return nil, err |
| + } |
| + if r.StatusCode != 200 { |
| + return nil, fmt.Errorf("Failed to fetch %s, status code %d", URL, r.StatusCode) |
| + } |
| + defer r.Body.Close() |
| + // Strip out the jsonp header, which is ")]}'" |
| + trash := make([]byte, 4) |
| + r.Body.Read(trash) // Read the jsonp header |
| + commits := Commit{} |
| + if err := json.NewDecoder(r.Body).Decode(&commits); err != nil { |
| + return nil, err |
| + } |
| + // TODO(hinoka): Follow paging |
|
estaab
2016/08/04 23:21:25
add more details
hinoka
2016/08/05 00:10:42
Done.
|
| + |
| + // Move things into our own datastructure. |
| + result := make([]resp.Commit, len(commits.Log)) |
| + for i, log := range commits.Log { |
| + result[i] = resp.Commit{ |
| + AuthorName: log.Author.Name, |
| + AuthorEmail: log.Author.Email, |
| + Repo: repoURL, |
| + Revision: log.Commit, |
| + Description: log.Message, |
| + Title: strings.SplitN(log.Message, "\n", 2)[0], |
| + // TODO(hinoka): The other stuff |
|
estaab
2016/08/04 23:21:25
add more details
hinoka
2016/08/05 00:10:42
Done.
|
| + } |
| + } |
| + return result, nil |
| +} |