github.com/google/go-github/v60@v60.0.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/rest/git/refs#get-a-reference
    53  //
    54  //meta:operation GET /repos/{owner}/{repo}/git/ref/{ref}
    55  func (s *GitService) GetRef(ctx context.Context, owner string, repo string, ref string) (*Reference, *Response, error) {
    56  	ref = strings.TrimPrefix(ref, "refs/")
    57  	u := fmt.Sprintf("repos/%v/%v/git/ref/%v", owner, repo, refURLEscape(ref))
    58  	req, err := s.client.NewRequest("GET", u, nil)
    59  	if err != nil {
    60  		return nil, nil, err
    61  	}
    62  
    63  	r := new(Reference)
    64  	resp, err := s.client.Do(ctx, req, r)
    65  	if err != nil {
    66  		return nil, resp, err
    67  	}
    68  
    69  	return r, resp, nil
    70  }
    71  
    72  // refURLEscape escapes every path segment of the given ref. Those must
    73  // not contain escaped "/" - as "%2F" - or github will not recognize it.
    74  func refURLEscape(ref string) string {
    75  	parts := strings.Split(ref, "/")
    76  	for i, s := range parts {
    77  		parts[i] = url.PathEscape(s)
    78  	}
    79  	return strings.Join(parts, "/")
    80  }
    81  
    82  // ReferenceListOptions specifies optional parameters to the
    83  // GitService.ListMatchingRefs method.
    84  type ReferenceListOptions struct {
    85  	Ref string `url:"-"`
    86  
    87  	ListOptions
    88  }
    89  
    90  // ListMatchingRefs lists references in a repository that match a supplied ref.
    91  // Use an empty ref to list all references.
    92  //
    93  // GitHub API docs: https://docs.github.com/rest/git/refs#list-matching-references
    94  //
    95  //meta:operation GET /repos/{owner}/{repo}/git/matching-refs/{ref}
    96  func (s *GitService) ListMatchingRefs(ctx context.Context, owner, repo string, opts *ReferenceListOptions) ([]*Reference, *Response, error) {
    97  	var ref string
    98  	if opts != nil {
    99  		ref = strings.TrimPrefix(opts.Ref, "refs/")
   100  	}
   101  	u := fmt.Sprintf("repos/%v/%v/git/matching-refs/%v", owner, repo, refURLEscape(ref))
   102  	u, err := addOptions(u, opts)
   103  	if err != nil {
   104  		return nil, nil, err
   105  	}
   106  
   107  	req, err := s.client.NewRequest("GET", u, nil)
   108  	if err != nil {
   109  		return nil, nil, err
   110  	}
   111  
   112  	var rs []*Reference
   113  	resp, err := s.client.Do(ctx, req, &rs)
   114  	if err != nil {
   115  		return nil, resp, err
   116  	}
   117  
   118  	return rs, resp, nil
   119  }
   120  
   121  // CreateRef creates a new ref in a repository.
   122  //
   123  // GitHub API docs: https://docs.github.com/rest/git/refs#create-a-reference
   124  //
   125  //meta:operation POST /repos/{owner}/{repo}/git/refs
   126  func (s *GitService) CreateRef(ctx context.Context, owner string, repo string, ref *Reference) (*Reference, *Response, error) {
   127  	u := fmt.Sprintf("repos/%v/%v/git/refs", owner, repo)
   128  	req, err := s.client.NewRequest("POST", u, &createRefRequest{
   129  		// back-compat with previous behavior that didn't require 'refs/' prefix
   130  		Ref: String("refs/" + strings.TrimPrefix(*ref.Ref, "refs/")),
   131  		SHA: ref.Object.SHA,
   132  	})
   133  	if err != nil {
   134  		return nil, nil, err
   135  	}
   136  
   137  	r := new(Reference)
   138  	resp, err := s.client.Do(ctx, req, r)
   139  	if err != nil {
   140  		return nil, resp, err
   141  	}
   142  
   143  	return r, resp, nil
   144  }
   145  
   146  // UpdateRef updates an existing ref in a repository.
   147  //
   148  // GitHub API docs: https://docs.github.com/rest/git/refs#update-a-reference
   149  //
   150  //meta:operation PATCH /repos/{owner}/{repo}/git/refs/{ref}
   151  func (s *GitService) UpdateRef(ctx context.Context, owner string, repo string, ref *Reference, force bool) (*Reference, *Response, error) {
   152  	refPath := strings.TrimPrefix(*ref.Ref, "refs/")
   153  	u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, refURLEscape(refPath))
   154  	req, err := s.client.NewRequest("PATCH", u, &updateRefRequest{
   155  		SHA:   ref.Object.SHA,
   156  		Force: &force,
   157  	})
   158  	if err != nil {
   159  		return nil, nil, err
   160  	}
   161  
   162  	r := new(Reference)
   163  	resp, err := s.client.Do(ctx, req, r)
   164  	if err != nil {
   165  		return nil, resp, err
   166  	}
   167  
   168  	return r, resp, nil
   169  }
   170  
   171  // DeleteRef deletes a ref from a repository.
   172  //
   173  // GitHub API docs: https://docs.github.com/rest/git/refs#delete-a-reference
   174  //
   175  //meta:operation DELETE /repos/{owner}/{repo}/git/refs/{ref}
   176  func (s *GitService) DeleteRef(ctx context.Context, owner string, repo string, ref string) (*Response, error) {
   177  	ref = strings.TrimPrefix(ref, "refs/")
   178  	u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, refURLEscape(ref))
   179  	req, err := s.client.NewRequest("DELETE", u, nil)
   180  	if err != nil {
   181  		return nil, err
   182  	}
   183  
   184  	return s.client.Do(ctx, req, nil)
   185  }