github.com/google/go-github/v57@v57.0.0/github/git_trees.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  	"encoding/json"
    11  	"fmt"
    12  )
    13  
    14  // Tree represents a GitHub tree.
    15  type Tree struct {
    16  	SHA     *string      `json:"sha,omitempty"`
    17  	Entries []*TreeEntry `json:"tree,omitempty"`
    18  
    19  	// Truncated is true if the number of items in the tree
    20  	// exceeded GitHub's maximum limit and the Entries were truncated
    21  	// in the response. Only populated for requests that fetch
    22  	// trees like Git.GetTree.
    23  	Truncated *bool `json:"truncated,omitempty"`
    24  }
    25  
    26  func (t Tree) String() string {
    27  	return Stringify(t)
    28  }
    29  
    30  // TreeEntry represents the contents of a tree structure. TreeEntry can
    31  // represent either a blob, a commit (in the case of a submodule), or another
    32  // tree.
    33  type TreeEntry struct {
    34  	SHA     *string `json:"sha,omitempty"`
    35  	Path    *string `json:"path,omitempty"`
    36  	Mode    *string `json:"mode,omitempty"`
    37  	Type    *string `json:"type,omitempty"`
    38  	Size    *int    `json:"size,omitempty"`
    39  	Content *string `json:"content,omitempty"`
    40  	URL     *string `json:"url,omitempty"`
    41  }
    42  
    43  func (t TreeEntry) String() string {
    44  	return Stringify(t)
    45  }
    46  
    47  // treeEntryWithFileDelete is used internally to delete a file whose
    48  // Content and SHA fields are empty. It does this by removing the "omitempty"
    49  // tag modifier on the SHA field which causes the GitHub API to receive
    50  // {"sha":null} and thereby delete the file.
    51  type treeEntryWithFileDelete struct {
    52  	SHA     *string `json:"sha"`
    53  	Path    *string `json:"path,omitempty"`
    54  	Mode    *string `json:"mode,omitempty"`
    55  	Type    *string `json:"type,omitempty"`
    56  	Size    *int    `json:"size,omitempty"`
    57  	Content *string `json:"content,omitempty"`
    58  	URL     *string `json:"url,omitempty"`
    59  }
    60  
    61  func (t *TreeEntry) MarshalJSON() ([]byte, error) {
    62  	if t.SHA == nil && t.Content == nil {
    63  		return json.Marshal(struct {
    64  			SHA  *string `json:"sha"`
    65  			Path *string `json:"path,omitempty"`
    66  			Mode *string `json:"mode,omitempty"`
    67  			Type *string `json:"type,omitempty"`
    68  		}{
    69  			nil,
    70  			t.Path,
    71  			t.Mode,
    72  			t.Type,
    73  		})
    74  	}
    75  	return json.Marshal(struct {
    76  		SHA     *string `json:"sha,omitempty"`
    77  		Path    *string `json:"path,omitempty"`
    78  		Mode    *string `json:"mode,omitempty"`
    79  		Type    *string `json:"type,omitempty"`
    80  		Size    *int    `json:"size,omitempty"`
    81  		Content *string `json:"content,omitempty"`
    82  		URL     *string `json:"url,omitempty"`
    83  	}{
    84  		SHA:     t.SHA,
    85  		Path:    t.Path,
    86  		Mode:    t.Mode,
    87  		Type:    t.Type,
    88  		Size:    t.Size,
    89  		Content: t.Content,
    90  		URL:     t.URL,
    91  	})
    92  }
    93  
    94  // GetTree fetches the Tree object for a given sha hash from a repository.
    95  //
    96  // GitHub API docs: https://docs.github.com/rest/git/trees#get-a-tree
    97  //
    98  //meta:operation GET /repos/{owner}/{repo}/git/trees/{tree_sha}
    99  func (s *GitService) GetTree(ctx context.Context, owner string, repo string, sha string, recursive bool) (*Tree, *Response, error) {
   100  	u := fmt.Sprintf("repos/%v/%v/git/trees/%v", owner, repo, sha)
   101  	if recursive {
   102  		u += "?recursive=1"
   103  	}
   104  
   105  	req, err := s.client.NewRequest("GET", u, nil)
   106  	if err != nil {
   107  		return nil, nil, err
   108  	}
   109  
   110  	t := new(Tree)
   111  	resp, err := s.client.Do(ctx, req, t)
   112  	if err != nil {
   113  		return nil, resp, err
   114  	}
   115  
   116  	return t, resp, nil
   117  }
   118  
   119  // createTree represents the body of a CreateTree request.
   120  type createTree struct {
   121  	BaseTree string        `json:"base_tree,omitempty"`
   122  	Entries  []interface{} `json:"tree"`
   123  }
   124  
   125  // CreateTree creates a new tree in a repository. If both a tree and a nested
   126  // path modifying that tree are specified, it will overwrite the contents of
   127  // that tree with the new path contents and write a new tree out.
   128  //
   129  // GitHub API docs: https://docs.github.com/rest/git/trees#create-a-tree
   130  //
   131  //meta:operation POST /repos/{owner}/{repo}/git/trees
   132  func (s *GitService) CreateTree(ctx context.Context, owner string, repo string, baseTree string, entries []*TreeEntry) (*Tree, *Response, error) {
   133  	u := fmt.Sprintf("repos/%v/%v/git/trees", owner, repo)
   134  
   135  	newEntries := make([]interface{}, 0, len(entries))
   136  	for _, entry := range entries {
   137  		if entry.Content == nil && entry.SHA == nil {
   138  			newEntries = append(newEntries, treeEntryWithFileDelete{
   139  				Path: entry.Path,
   140  				Mode: entry.Mode,
   141  				Type: entry.Type,
   142  				Size: entry.Size,
   143  				URL:  entry.URL,
   144  			})
   145  			continue
   146  		}
   147  		newEntries = append(newEntries, entry)
   148  	}
   149  
   150  	body := &createTree{
   151  		BaseTree: baseTree,
   152  		Entries:  newEntries,
   153  	}
   154  	req, err := s.client.NewRequest("POST", u, body)
   155  	if err != nil {
   156  		return nil, nil, err
   157  	}
   158  
   159  	t := new(Tree)
   160  	resp, err := s.client.Do(ctx, req, t)
   161  	if err != nil {
   162  		return nil, resp, err
   163  	}
   164  
   165  	return t, resp, nil
   166  }