github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/git/tree_nogogit.go (about)

     1  // Copyright 2023 The GitBundle Inc. All rights reserved.
     2  // Copyright 2017 The Gitea Authors. All rights reserved.
     3  // Use of this source code is governed by a MIT-style
     4  // license that can be found in the LICENSE file.
     5  
     6  //go:build !gogit
     7  
     8  package git
     9  
    10  import (
    11  	"io"
    12  	"math"
    13  	"strings"
    14  )
    15  
    16  // Tree represents a flat directory listing.
    17  type Tree struct {
    18  	ID         SHA1
    19  	ResolvedID SHA1
    20  	repo       *Repository
    21  
    22  	// parent tree
    23  	ptree *Tree
    24  
    25  	entries       Entries
    26  	entriesParsed bool
    27  
    28  	entriesRecursive       Entries
    29  	entriesRecursiveParsed bool
    30  }
    31  
    32  // ListEntries returns all entries of current tree.
    33  func (t *Tree) ListEntries() (Entries, error) {
    34  	if t.entriesParsed {
    35  		return t.entries, nil
    36  	}
    37  
    38  	if t.repo != nil {
    39  		wr, rd, cancel := t.repo.CatFileBatch(t.repo.Ctx)
    40  		defer cancel()
    41  
    42  		_, _ = wr.Write([]byte(t.ID.String() + "\n"))
    43  		_, typ, sz, err := ReadBatchLine(rd)
    44  		if err != nil {
    45  			return nil, err
    46  		}
    47  		if typ == "commit" {
    48  			treeID, err := ReadTreeID(rd, sz)
    49  			if err != nil && err != io.EOF {
    50  				return nil, err
    51  			}
    52  			_, _ = wr.Write([]byte(treeID + "\n"))
    53  			_, typ, sz, err = ReadBatchLine(rd)
    54  			if err != nil {
    55  				return nil, err
    56  			}
    57  		}
    58  		if typ == "tree" {
    59  			t.entries, err = catBatchParseTreeEntries(t, rd, sz)
    60  			if err != nil {
    61  				return nil, err
    62  			}
    63  			t.entriesParsed = true
    64  			return t.entries, nil
    65  		}
    66  
    67  		// Not a tree just use ls-tree instead
    68  		for sz > math.MaxInt32 {
    69  			discarded, err := rd.Discard(math.MaxInt32)
    70  			sz -= int64(discarded)
    71  			if err != nil {
    72  				return nil, err
    73  			}
    74  		}
    75  		for sz > 0 {
    76  			discarded, err := rd.Discard(int(sz))
    77  			sz -= int64(discarded)
    78  			if err != nil {
    79  				return nil, err
    80  			}
    81  		}
    82  	}
    83  
    84  	stdout, _, runErr := NewCommand(t.repo.Ctx, "ls-tree", "-l", t.ID.String()).RunStdBytes(&RunOpts{Dir: t.repo.Path})
    85  	if runErr != nil {
    86  		if strings.Contains(runErr.Error(), "fatal: Not a valid object name") || strings.Contains(runErr.Error(), "fatal: not a tree object") {
    87  			return nil, ErrNotExist{
    88  				ID: t.ID.String(),
    89  			}
    90  		}
    91  		return nil, runErr
    92  	}
    93  
    94  	var err error
    95  	t.entries, err = parseTreeEntries(stdout, t)
    96  	if err == nil {
    97  		t.entriesParsed = true
    98  	}
    99  
   100  	return t.entries, err
   101  }
   102  
   103  // ListEntriesRecursive returns all entries of current tree recursively including all subtrees
   104  func (t *Tree) ListEntriesRecursive() (Entries, error) {
   105  	if t.entriesRecursiveParsed {
   106  		return t.entriesRecursive, nil
   107  	}
   108  
   109  	stdout, _, runErr := NewCommand(t.repo.Ctx, "ls-tree", "-t", "-l", "-r", t.ID.String()).RunStdBytes(&RunOpts{Dir: t.repo.Path})
   110  	if runErr != nil {
   111  		return nil, runErr
   112  	}
   113  
   114  	var err error
   115  	t.entriesRecursive, err = parseTreeEntries(stdout, t)
   116  	if err == nil {
   117  		t.entriesRecursiveParsed = true
   118  	}
   119  
   120  	return t.entriesRecursive, err
   121  }