github.com/google/go-github/v49@v49.1.0/github/git_refs.go (about) 1 // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 package github 7 8 import ( 9 "context" 10 "fmt" 11 "net/url" 12 "strings" 13 ) 14 15 // Reference represents a GitHub reference. 16 type Reference struct { 17 Ref *string `json:"ref"` 18 URL *string `json:"url"` 19 Object *GitObject `json:"object"` 20 NodeID *string `json:"node_id,omitempty"` 21 } 22 23 func (r Reference) String() string { 24 return Stringify(r) 25 } 26 27 // GitObject represents a Git object. 28 type GitObject struct { 29 Type *string `json:"type"` 30 SHA *string `json:"sha"` 31 URL *string `json:"url"` 32 } 33 34 func (o GitObject) String() string { 35 return Stringify(o) 36 } 37 38 // createRefRequest represents the payload for creating a reference. 39 type createRefRequest struct { 40 Ref *string `json:"ref"` 41 SHA *string `json:"sha"` 42 } 43 44 // updateRefRequest represents the payload for updating a reference. 45 type updateRefRequest struct { 46 SHA *string `json:"sha"` 47 Force *bool `json:"force"` 48 } 49 50 // GetRef fetches a single reference in a repository. 51 // 52 // GitHub API docs: https://docs.github.com/en/rest/git/refs#get-a-reference 53 func (s *GitService) GetRef(ctx context.Context, owner string, repo string, ref string) (*Reference, *Response, error) { 54 ref = strings.TrimPrefix(ref, "refs/") 55 u := fmt.Sprintf("repos/%v/%v/git/ref/%v", owner, repo, refURLEscape(ref)) 56 req, err := s.client.NewRequest("GET", u, nil) 57 if err != nil { 58 return nil, nil, err 59 } 60 61 r := new(Reference) 62 resp, err := s.client.Do(ctx, req, r) 63 if err != nil { 64 return nil, resp, err 65 } 66 67 return r, resp, nil 68 } 69 70 // refURLEscape escapes every path segment of the given ref. Those must 71 // not contain escaped "/" - as "%2F" - or github will not recognize it. 72 func refURLEscape(ref string) string { 73 parts := strings.Split(ref, "/") 74 for i, s := range parts { 75 parts[i] = url.PathEscape(s) 76 } 77 return strings.Join(parts, "/") 78 } 79 80 // ReferenceListOptions specifies optional parameters to the 81 // GitService.ListMatchingRefs method. 82 type ReferenceListOptions struct { 83 Ref string `url:"-"` 84 85 ListOptions 86 } 87 88 // ListMatchingRefs lists references in a repository that match a supplied ref. 89 // Use an empty ref to list all references. 90 // 91 // GitHub API docs: https://docs.github.com/en/rest/git/refs#list-matching-references 92 func (s *GitService) ListMatchingRefs(ctx context.Context, owner, repo string, opts *ReferenceListOptions) ([]*Reference, *Response, error) { 93 var ref string 94 if opts != nil { 95 ref = strings.TrimPrefix(opts.Ref, "refs/") 96 } 97 u := fmt.Sprintf("repos/%v/%v/git/matching-refs/%v", owner, repo, refURLEscape(ref)) 98 u, err := addOptions(u, opts) 99 if err != nil { 100 return nil, nil, err 101 } 102 103 req, err := s.client.NewRequest("GET", u, nil) 104 if err != nil { 105 return nil, nil, err 106 } 107 108 var rs []*Reference 109 resp, err := s.client.Do(ctx, req, &rs) 110 if err != nil { 111 return nil, resp, err 112 } 113 114 return rs, resp, nil 115 } 116 117 // CreateRef creates a new ref in a repository. 118 // 119 // GitHub API docs: https://docs.github.com/en/rest/git/refs#create-a-reference 120 func (s *GitService) CreateRef(ctx context.Context, owner string, repo string, ref *Reference) (*Reference, *Response, error) { 121 u := fmt.Sprintf("repos/%v/%v/git/refs", owner, repo) 122 req, err := s.client.NewRequest("POST", u, &createRefRequest{ 123 // back-compat with previous behavior that didn't require 'refs/' prefix 124 Ref: String("refs/" + strings.TrimPrefix(*ref.Ref, "refs/")), 125 SHA: ref.Object.SHA, 126 }) 127 if err != nil { 128 return nil, nil, err 129 } 130 131 r := new(Reference) 132 resp, err := s.client.Do(ctx, req, r) 133 if err != nil { 134 return nil, resp, err 135 } 136 137 return r, resp, nil 138 } 139 140 // UpdateRef updates an existing ref in a repository. 141 // 142 // GitHub API docs: https://docs.github.com/en/rest/git/refs#update-a-reference 143 func (s *GitService) UpdateRef(ctx context.Context, owner string, repo string, ref *Reference, force bool) (*Reference, *Response, error) { 144 refPath := strings.TrimPrefix(*ref.Ref, "refs/") 145 u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, refURLEscape(refPath)) 146 req, err := s.client.NewRequest("PATCH", u, &updateRefRequest{ 147 SHA: ref.Object.SHA, 148 Force: &force, 149 }) 150 if err != nil { 151 return nil, nil, err 152 } 153 154 r := new(Reference) 155 resp, err := s.client.Do(ctx, req, r) 156 if err != nil { 157 return nil, resp, err 158 } 159 160 return r, resp, nil 161 } 162 163 // DeleteRef deletes a ref from a repository. 164 // 165 // GitHub API docs: https://docs.github.com/en/rest/git/refs#delete-a-reference 166 func (s *GitService) DeleteRef(ctx context.Context, owner string, repo string, ref string) (*Response, error) { 167 ref = strings.TrimPrefix(ref, "refs/") 168 u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, refURLEscape(ref)) 169 req, err := s.client.NewRequest("DELETE", u, nil) 170 if err != nil { 171 return nil, err 172 } 173 174 return s.client.Do(ctx, req, nil) 175 }