code.gitea.io/gitea@v1.22.3/modules/git/tree_nogogit.go (about)

     1  // Copyright 2020 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  //go:build !gogit
     5  
     6  package git
     7  
     8  import (
     9  	"io"
    10  	"strings"
    11  )
    12  
    13  // Tree represents a flat directory listing.
    14  type Tree struct {
    15  	ID         ObjectID
    16  	ResolvedID ObjectID
    17  	repo       *Repository
    18  
    19  	// parent tree
    20  	ptree *Tree
    21  
    22  	entries       Entries
    23  	entriesParsed bool
    24  
    25  	entriesRecursive       Entries
    26  	entriesRecursiveParsed bool
    27  }
    28  
    29  // ListEntries returns all entries of current tree.
    30  func (t *Tree) ListEntries() (Entries, error) {
    31  	if t.entriesParsed {
    32  		return t.entries, nil
    33  	}
    34  
    35  	if t.repo != nil {
    36  		wr, rd, cancel, err := t.repo.CatFileBatch(t.repo.Ctx)
    37  		if err != nil {
    38  			return nil, err
    39  		}
    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.ID.Type(), 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  		if err := DiscardFull(rd, sz+1); err != nil {
    69  			return nil, err
    70  		}
    71  	}
    72  
    73  	stdout, _, runErr := NewCommand(t.repo.Ctx, "ls-tree", "-l").AddDynamicArguments(t.ID.String()).RunStdBytes(&RunOpts{Dir: t.repo.Path})
    74  	if runErr != nil {
    75  		if strings.Contains(runErr.Error(), "fatal: Not a valid object name") || strings.Contains(runErr.Error(), "fatal: not a tree object") {
    76  			return nil, ErrNotExist{
    77  				ID: t.ID.String(),
    78  			}
    79  		}
    80  		return nil, runErr
    81  	}
    82  
    83  	objectFormat, err := t.repo.GetObjectFormat()
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  	t.entries, err = parseTreeEntries(objectFormat, stdout, t)
    88  	if err == nil {
    89  		t.entriesParsed = true
    90  	}
    91  
    92  	return t.entries, err
    93  }
    94  
    95  // listEntriesRecursive returns all entries of current tree recursively including all subtrees
    96  // extraArgs could be "-l" to get the size, which is slower
    97  func (t *Tree) listEntriesRecursive(extraArgs TrustedCmdArgs) (Entries, error) {
    98  	if t.entriesRecursiveParsed {
    99  		return t.entriesRecursive, nil
   100  	}
   101  
   102  	stdout, _, runErr := NewCommand(t.repo.Ctx, "ls-tree", "-t", "-r").
   103  		AddArguments(extraArgs...).
   104  		AddDynamicArguments(t.ID.String()).
   105  		RunStdBytes(&RunOpts{Dir: t.repo.Path})
   106  	if runErr != nil {
   107  		return nil, runErr
   108  	}
   109  
   110  	objectFormat, err := t.repo.GetObjectFormat()
   111  	if err != nil {
   112  		return nil, err
   113  	}
   114  	t.entriesRecursive, err = parseTreeEntries(objectFormat, stdout, t)
   115  	if err == nil {
   116  		t.entriesRecursiveParsed = true
   117  	}
   118  
   119  	return t.entriesRecursive, err
   120  }
   121  
   122  // ListEntriesRecursiveFast returns all entries of current tree recursively including all subtrees, no size
   123  func (t *Tree) ListEntriesRecursiveFast() (Entries, error) {
   124  	return t.listEntriesRecursive(nil)
   125  }
   126  
   127  // ListEntriesRecursiveWithSize returns all entries of current tree recursively including all subtrees, with size
   128  func (t *Tree) ListEntriesRecursiveWithSize() (Entries, error) {
   129  	return t.listEntriesRecursive(TrustedCmdArgs{"--long"})
   130  }