// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package github

import (
	
	
	
	
)

// Reference represents a GitHub reference.
type Reference struct {
	Ref    *string    `json:"ref"`
	URL    *string    `json:"url"`
	Object *GitObject `json:"object"`
	NodeID *string    `json:"node_id,omitempty"`
}

func ( Reference) () string {
	return Stringify()
}

// GitObject represents a Git object.
type GitObject struct {
	Type *string `json:"type"`
	SHA  *string `json:"sha"`
	URL  *string `json:"url"`
}

func ( GitObject) () string {
	return Stringify()
}

// createRefRequest represents the payload for creating a reference.
type createRefRequest struct {
	Ref *string `json:"ref"`
	SHA *string `json:"sha"`
}

// updateRefRequest represents the payload for updating a reference.
type updateRefRequest struct {
	SHA   *string `json:"sha"`
	Force *bool   `json:"force"`
}

// GetRef fetches a single reference in a repository.
//
// GitHub API docs: https://docs.github.com/rest/git/refs#get-a-reference
//
//meta:operation GET /repos/{owner}/{repo}/git/ref/{ref}
func ( *GitService) ( context.Context,  string,  string,  string) (*Reference, *Response, error) {
	 = strings.TrimPrefix(, "refs/")
	 := fmt.Sprintf("repos/%v/%v/git/ref/%v", , , refURLEscape())
	,  := .client.NewRequest("GET", , nil)
	if  != nil {
		return nil, nil, 
	}

	 := new(Reference)
	,  := .client.Do(, , )
	if  != nil {
		return nil, , 
	}

	return , , nil
}

// refURLEscape escapes every path segment of the given ref. Those must
// not contain escaped "/" - as "%2F" - or github will not recognize it.
func refURLEscape( string) string {
	 := strings.Split(, "/")
	for ,  := range  {
		[] = url.PathEscape()
	}
	return strings.Join(, "/")
}

// ReferenceListOptions specifies optional parameters to the
// GitService.ListMatchingRefs method.
type ReferenceListOptions struct {
	Ref string `url:"-"`

	ListOptions
}

// ListMatchingRefs lists references in a repository that match a supplied ref.
// Use an empty ref to list all references.
//
// GitHub API docs: https://docs.github.com/rest/git/refs#list-matching-references
//
//meta:operation GET /repos/{owner}/{repo}/git/matching-refs/{ref}
func ( *GitService) ( context.Context, ,  string,  *ReferenceListOptions) ([]*Reference, *Response, error) {
	var  string
	if  != nil {
		 = strings.TrimPrefix(.Ref, "refs/")
	}
	 := fmt.Sprintf("repos/%v/%v/git/matching-refs/%v", , , refURLEscape())
	,  := addOptions(, )
	if  != nil {
		return nil, nil, 
	}

	,  := .client.NewRequest("GET", , nil)
	if  != nil {
		return nil, nil, 
	}

	var  []*Reference
	,  := .client.Do(, , &)
	if  != nil {
		return nil, , 
	}

	return , , nil
}

// CreateRef creates a new ref in a repository.
//
// GitHub API docs: https://docs.github.com/rest/git/refs#create-a-reference
//
//meta:operation POST /repos/{owner}/{repo}/git/refs
func ( *GitService) ( context.Context,  string,  string,  *Reference) (*Reference, *Response, error) {
	 := fmt.Sprintf("repos/%v/%v/git/refs", , )
	,  := .client.NewRequest("POST", , &createRefRequest{
		// back-compat with previous behavior that didn't require 'refs/' prefix
		Ref: String("refs/" + strings.TrimPrefix(*.Ref, "refs/")),
		SHA: .Object.SHA,
	})
	if  != nil {
		return nil, nil, 
	}

	 := new(Reference)
	,  := .client.Do(, , )
	if  != nil {
		return nil, , 
	}

	return , , nil
}

// UpdateRef updates an existing ref in a repository.
//
// GitHub API docs: https://docs.github.com/rest/git/refs#update-a-reference
//
//meta:operation PATCH /repos/{owner}/{repo}/git/refs/{ref}
func ( *GitService) ( context.Context,  string,  string,  *Reference,  bool) (*Reference, *Response, error) {
	 := strings.TrimPrefix(*.Ref, "refs/")
	 := fmt.Sprintf("repos/%v/%v/git/refs/%v", , , refURLEscape())
	,  := .client.NewRequest("PATCH", , &updateRefRequest{
		SHA:   .Object.SHA,
		Force: &,
	})
	if  != nil {
		return nil, nil, 
	}

	 := new(Reference)
	,  := .client.Do(, , )
	if  != nil {
		return nil, , 
	}

	return , , nil
}

// DeleteRef deletes a ref from a repository.
//
// GitHub API docs: https://docs.github.com/rest/git/refs#delete-a-reference
//
//meta:operation DELETE /repos/{owner}/{repo}/git/refs/{ref}
func ( *GitService) ( context.Context,  string,  string,  string) (*Response, error) {
	 = strings.TrimPrefix(, "refs/")
	 := fmt.Sprintf("repos/%v/%v/git/refs/%v", , , refURLEscape())
	,  := .client.NewRequest("DELETE", , nil)
	if  != nil {
		return nil, 
	}

	return .client.Do(, , nil)
}