github.com/posener/gitfs@v1.2.2-0.20200410105819-ea4e48d73ab9/internal/githubfs/getatree.go (about)

     1  package githubfs
     2  
     3  import (
     4  	"context"
     5  	"encoding/base64"
     6  	"strings"
     7  
     8  	"github.com/pkg/errors"
     9  	"github.com/posener/gitfs/internal/tree"
    10  )
    11  
    12  // getATree gets github tree using Github's get-a-tree API:
    13  // https://developer.github.com/v3/git/trees/#get-a-tree.
    14  // The content provider returns the file content only when accessed.
    15  type getATree githubfs
    16  
    17  func (fs *getATree) get(ctx context.Context) (tree.Tree, error) {
    18  	gitTree, _, err := fs.client.Git.GetTree(ctx, fs.owner, fs.repo, fs.ref, true)
    19  	if err != nil {
    20  		return nil, errors.Wrap(err, "get git tree")
    21  	}
    22  	t := make(tree.Tree)
    23  	for _, entry := range gitTree.Entries {
    24  		path := entry.GetPath()
    25  		if fs.path != "" {
    26  			if !strings.HasPrefix(path, fs.path) {
    27  				continue
    28  			}
    29  			path = strings.TrimPrefix(path, fs.path)
    30  		}
    31  
    32  		var err error
    33  		switch entry.GetType() {
    34  		case "tree": // A directory.
    35  			if !fs.glob.Match(path, true) {
    36  				continue
    37  			}
    38  			err = t.AddDir(path)
    39  		case "blob": // A file.
    40  			if !fs.glob.Match(path, false) {
    41  				continue
    42  			}
    43  			err = t.AddFile(path, entry.GetSize(), fs.contentLoader(entry.GetSHA()))
    44  		}
    45  		if err != nil {
    46  			return nil, errors.Wrapf(err, "adding %s", path)
    47  		}
    48  	}
    49  	return t, nil
    50  }
    51  
    52  // contentLoader gets content of git blob according to git sha of that blob.
    53  func (fs *getATree) contentLoader(sha string) func(context.Context) ([]byte, error) {
    54  	return func(ctx context.Context) ([]byte, error) {
    55  		blob, _, err := fs.client.Git.GetBlob(ctx, fs.owner, fs.repo, sha)
    56  		if err != nil {
    57  			return nil, errors.Wrap(err, "failed getting blob")
    58  		}
    59  		switch encoding := blob.GetEncoding(); encoding {
    60  		case "base64":
    61  			return base64.StdEncoding.DecodeString(blob.GetContent())
    62  		default:
    63  			return nil, errors.Errorf("unexpected encoding: %s", encoding)
    64  		}
    65  	}
    66  }