Chromium Code Reviews| Index: common/api/gitiles/gitiles.go |
| diff --git a/common/api/gitiles/gitiles.go b/common/api/gitiles/gitiles.go |
| index bf7bd3341a646d844cf989773665f0f79b405474..6d206f1bc23ff3ab6be8d5aa9f4cf7d26ff2d1b5 100644 |
| --- a/common/api/gitiles/gitiles.go |
| +++ b/common/api/gitiles/gitiles.go |
| @@ -165,8 +165,72 @@ func (c *Client) Log(ctx context.Context, repoURL, treeish string, limit int) ([ |
| } |
| } |
| +// Refs returns a map resolving each ref in a repo to git revision. |
| +// |
| +// refsPath limits whcih refs to resolve to only those matching {refsPath}/*. |
|
Vadim Sh.
2017/07/20 21:09:09
which
tandrii(chromium)
2017/07/20 22:12:05
Done.
|
| +// refsPath should start with "refs" and should not include glob '*'. |
| +// Typically, "refs/heads" should be used. |
| +// |
| +// To fetch **all** refs in a repo, specify just "refs" but beware of two |
| +// caveats: |
| +// * refs returned include a ref for each patchset for each Gerrit change |
| +// associated with the repo |
| +// * returned map will contain special "HEAD" ref whose value in resulting map |
| +// will be name of the actual ref to which "HEAD" points, which is typically |
| +// "refs/heads/master". |
| +// |
| +// Thus, if you are looking for all tags and all branches of repo, it's |
| +// recommended to issue two Refs calls limited to "refs/tags" and "refs/heads" |
| +// instead of one call for "refs". |
| +// |
| +// Since Gerrit allows per-ref ACLs, it is possible that some refs matching |
| +// refPrefix would not be present in results because current user isn't granted |
| +// read permission on them. |
| +func (c *Client) Refs(ctx context.Context, repoURL, refsPath string) (map[string]string, error) { |
| + repoURL, err := NormalizeRepoURL(repoURL) |
| + if err != nil { |
| + return nil, err |
| + } |
| + if !strings.HasPrefix(refsPath, "refs") { |
|
Vadim Sh.
2017/07/20 21:09:09
refsPath != "refs" && !strings.HasPrefix(refsPath,
tandrii(chromium)
2017/07/20 22:12:05
Done.
|
| + return nil, fmt.Errorf("refsPath must start with \"refs\": %q", refsPath) |
| + } |
| + refsPath = strings.TrimRight(refsPath, "/") |
| + |
| + subPath := fmt.Sprintf("+%s?format=json", url.PathEscape(refsPath)) |
| + resp := refsResponse{} |
| + if err := c.get(ctx, repoURL, subPath, &resp); err != nil { |
| + return nil, err |
| + } |
| + r := make(map[string]string, len(resp)) |
| + for ref, v := range resp { |
| + switch { |
| + case v.Value == "": |
| + // Weird case of what looks like hash with a target in at least Chromium |
| + // repo. |
| + continue |
| + case ref == "HEAD": |
| + r["HEAD"] = v.Target |
| + case refsPath != "refs": |
| + // Gitiles omits refsPath from each ref if refsPath != "refs". Undo this |
| + // inconsistency. |
| + r[refsPath+"/"+ref] = v.Value |
| + default: |
| + r[ref] = v.Value |
| + } |
| + } |
| + return r, nil |
| +} |
| + |
| //////////////////////////////////////////////////////////////////////////////// |
| +type refsResponseRefInfo struct { |
| + Value string `json:"value"` |
| + Target string `json:"target"` |
| +} |
| + |
| +// refsResponse is the JSON response from querying gitiles for a Refs request. |
| +type refsResponse map[string]refsResponseRefInfo |
| + |
| // logResponse is the JSON response from querying gitiles for a log request. |
| type logResponse struct { |
| Log []Commit `json:"log"` |