gerrit: add Client.GetProjectTags method, WebLinkInfo, TagInfo
Change-Id: Iebe0796ecd65b98b75b73b1f4008fef0177fb9c8
GitHub-Last-Rev: 5807f37ca6853c0a3d7036fc8fb383b687cc29a3
GitHub-Pull-Request: golang/build#13
Reviewed-on: https://go-review.googlesource.com/c/143838
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/gerrit/gerrit.go b/gerrit/gerrit.go
index dae01a7..6204ad0 100644
--- a/gerrit/gerrit.go
+++ b/gerrit/gerrit.go
@@ -307,6 +307,17 @@
TZOffset int `json:"tz"`
}
+func (gpi *GitPersonInfo) Equal(v *GitPersonInfo) bool {
+ if gpi == nil {
+ if gpi != v {
+ return false
+ }
+ return true
+ }
+ return gpi.Name == v.Name && gpi.Email == v.Email && gpi.Date.Equal(v.Date) &&
+ gpi.TZOffset == v.TZOffset
+}
+
type FileInfo struct {
Status string `json:"status"`
Binary bool `json:"binary"`
@@ -637,7 +648,8 @@
CanDelete bool `json:"can_delete"`
}
-// GetProjectBranches returns a project's branches.
+// GetProjectBranches returns the branches for the project name. The branches are stored in a map
+// keyed by reference.
func (c *Client) GetProjectBranches(ctx context.Context, name string) (map[string]BranchInfo, error) {
var res []BranchInfo
err := c.do(ctx, &res, "GET", fmt.Sprintf("/projects/%s/branches/", name))
@@ -651,6 +663,71 @@
return m, nil
}
+// WebLinkInfo is information about a web link.
+// See https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#web-link-info
+type WebLinkInfo struct {
+ Name string `json:"name"`
+ URL string `json:"url"`
+ ImageURL string `json:"image_url"`
+}
+
+func (wli *WebLinkInfo) Equal(v *WebLinkInfo) bool {
+ if wli == nil || v == nil {
+ return false
+ }
+ return wli.Name == v.Name && wli.URL == v.URL && wli.ImageURL == v.ImageURL
+}
+
+// TagInfo is information about a tag.
+// See https://gerrit-review.googlesource.com/Documentation/rest-api-projects.html#tag-info
+type TagInfo struct {
+ Ref string `json:"ref"`
+ Revision string `json:"revision"`
+ Object string `json:"object,omitempty"`
+ Message string `json:"message,omitempty"`
+ Tagger *GitPersonInfo `json:"tagger,omitempty"`
+ Created TimeStamp `json:"created,omitempty"`
+ CanDelete bool `json:"can_delete"`
+ WebLinks []WebLinkInfo `json:"web_links,omitempty"`
+}
+
+func (ti *TagInfo) Equal(v *TagInfo) bool {
+ if ti == nil || v == nil {
+ return false
+ }
+ if ti.Ref != v.Ref || ti.Revision != v.Revision || ti.Object != v.Object ||
+ ti.Message != v.Message || !ti.Created.Equal(v.Created) || ti.CanDelete != v.CanDelete {
+ return false
+ }
+ if !ti.Tagger.Equal(v.Tagger) {
+ return false
+ }
+ if len(ti.WebLinks) != len(v.WebLinks) {
+ return false
+ }
+ for i := range ti.WebLinks {
+ if !ti.WebLinks[i].Equal(&v.WebLinks[i]) {
+ return false
+ }
+ }
+ return true
+}
+
+// GetProjectTags returns the tags for the project name. The tags are stored in a map keyed by
+// reference.
+func (c *Client) GetProjectTags(ctx context.Context, name string) (map[string]TagInfo, error) {
+ var res []TagInfo
+ err := c.do(ctx, &res, "GET", fmt.Sprintf("/projects/%s/tags/", name))
+ if err != nil {
+ return nil, err
+ }
+ m := map[string]TagInfo{}
+ for _, ti := range res {
+ m[ti.Ref] = ti
+ }
+ return m, nil
+}
+
// GetAccountInfo gets the specified account's information from Gerrit.
// For the API call, see https://gerrit-review.googlesource.com/Documentation/rest-api-accounts.html#get-account
// The accountID is https://gerrit-review.googlesource.com/Documentation/rest-api-accounts.html#account-id
@@ -713,6 +790,10 @@
type TimeStamp time.Time
+func (ts TimeStamp) Equal(v TimeStamp) bool {
+ return ts.Time().Equal(v.Time())
+}
+
// Gerrit's timestamp layout is like time.RFC3339Nano, but with a space instead of the "T",
// and without a timezone (it's always in UTC).
const timeStampLayout = "2006-01-02 15:04:05.999999999"
diff --git a/gerrit/gerrit_test.go b/gerrit/gerrit_test.go
index b26c996..2ec6016 100644
--- a/gerrit/gerrit_test.go
+++ b/gerrit/gerrit_test.go
@@ -262,3 +262,79 @@
t.Errorf("expected %v, got %v", expected, ts.Time())
}
}
+
+// taken from https://gerrit-review.googlesource.com/Documentation/rest-api-projects.html#list-tags
+var exampleProjectTagsResponse = []byte(` )]}'
+ [
+ {
+ "ref": "refs/tags/v1.0",
+ "revision": "49ce77fdcfd3398dc0dedbe016d1a425fd52d666",
+ "object": "1624f5af8ae89148d1a3730df8c290413e3dcf30",
+ "message": "Annotated tag",
+ "tagger": {
+ "name": "David Pursehouse",
+ "email": "david.pursehouse@sonymobile.com",
+ "date": "2014-10-06 07:35:03.000000000",
+ "tz": 540
+ }
+ },
+ {
+ "ref": "refs/tags/v2.0",
+ "revision": "1624f5af8ae89148d1a3730df8c290413e3dcf30"
+ }
+ ]
+`)
+
+func TestGetProjectTags(t *testing.T) {
+ hitServer := false
+ path := ""
+ s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ hitServer = true
+ path = r.URL.Path
+ w.Header().Set("Content-Type", "application/json; charset=UTF-8")
+ w.WriteHeader(200)
+ w.Write(exampleProjectTagsResponse)
+ }))
+ defer s.Close()
+ c := NewClient(s.URL, NoAuth)
+ tags, err := c.GetProjectTags(context.Background(), "go")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !hitServer {
+ t.Errorf("expected to hit test server, didn't")
+ }
+ if path != "/projects/go/tags/" {
+ t.Errorf("expected Path to be '/projects/go/tags/', got %s", path)
+ }
+ expectedTags := map[string]TagInfo{
+ "refs/tags/v1.0": TagInfo{
+ Ref: "refs/tags/v1.0",
+ Revision: "49ce77fdcfd3398dc0dedbe016d1a425fd52d666",
+ Object: "1624f5af8ae89148d1a3730df8c290413e3dcf30",
+ Message: "Annotated tag",
+ Tagger: &GitPersonInfo{
+ Name: "David Pursehouse",
+ Email: "david.pursehouse@sonymobile.com",
+ Date: TimeStamp(time.Date(2014, 10, 6, 7, 35, 3, 0, time.UTC)),
+ TZOffset: 540,
+ },
+ },
+ "refs/tags/v2.0": TagInfo{
+ Ref: "refs/tags/v2.0",
+ Revision: "1624f5af8ae89148d1a3730df8c290413e3dcf30",
+ },
+ }
+ if len(tags) != len(expectedTags) {
+ t.Errorf("expected %d tags, got %d", len(expectedTags), len(tags))
+ }
+ for ref, tag := range tags {
+ expectedTag, found := expectedTags[ref]
+ if !found {
+ t.Errorf("unexpected tag %q", ref)
+ }
+ if !tag.Equal(&expectedTag) {
+ t.Errorf("tags don't match (expected %#v and got %#v)", expectedTag, tag)
+ }
+ }
+}