mirror of
https://github.com/go-gitea/gitea.git
synced 2026-07-21 22:05:17 +02:00
before: gitrepo vs git packages after: git package fully handle all git operations by the way, use `WithRepo(repo)` instead of `WithDir(repo.Path)` to hide path details. benefits: 1. remove all unnecessary wrappers, developers no need to struggle with "which package should be used" 2. simplify code, RepositoryFacade can (will) be used everywhere, all "path" details are (will be) hidden
108 lines
2.9 KiB
Go
108 lines
2.9 KiB
Go
// Copyright 2020 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
//go:build !gogit
|
|
|
|
package git
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
|
|
"gitea.dev/modules/git/gitcmd"
|
|
)
|
|
|
|
// Tree represents a flat directory listing.
|
|
type Tree struct {
|
|
TreeCommon
|
|
|
|
entries Entries
|
|
entriesParsed bool
|
|
}
|
|
|
|
// ListEntries returns all entries of current tree.
|
|
func (t *Tree) ListEntries(ctx context.Context, gitRepo *Repository) (Entries, error) {
|
|
if t.entriesParsed {
|
|
return t.entries, nil
|
|
}
|
|
|
|
batch, cancel, err := gitRepo.CatFileBatch(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer cancel()
|
|
|
|
info, rd, err := batch.QueryContent(t.ID.String())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if info.Type == "commit" {
|
|
treeID, err := ReadTreeID(rd, info.Size)
|
|
if err != nil && err != io.EOF {
|
|
return nil, err
|
|
}
|
|
info, rd, err = batch.QueryContent(treeID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
if info.Type == "tree" {
|
|
t.entries, err = catBatchParseTreeEntries(t.ID.Type(), t, rd, info.Size)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
t.entriesParsed = true
|
|
return t.entries, nil
|
|
}
|
|
|
|
// Not a tree just use ls-tree instead
|
|
if err := DiscardFull(rd, info.Size+1); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
stdout, _, runErr := gitcmd.NewCommand("ls-tree", "-l").AddDynamicArguments(t.ID.String()).WithRepo(gitRepo).RunStdBytes(ctx)
|
|
if runErr != nil {
|
|
if gitcmd.IsStderr(runErr, gitcmd.StderrNotValidObjectName) || gitcmd.IsStderr(runErr, gitcmd.StderrNotTreeObject) {
|
|
return nil, ErrNotExist{
|
|
ID: t.ID.String(),
|
|
}
|
|
}
|
|
return nil, runErr
|
|
}
|
|
|
|
t.entries, err = parseTreeEntries(stdout, t)
|
|
if err == nil {
|
|
t.entriesParsed = true
|
|
}
|
|
|
|
return t.entries, err
|
|
}
|
|
|
|
// listEntriesRecursive returns all entries of current tree recursively including all subtrees
|
|
// extraArgs could be "-l" to get the size, which is slower
|
|
func (t *Tree) listEntriesRecursive(ctx context.Context, gitRepo *Repository, extraArgs gitcmd.TrustedCmdArgs) (Entries, error) {
|
|
stdout, _, runErr := gitcmd.NewCommand("ls-tree", "-t", "-r").
|
|
AddArguments(extraArgs...).
|
|
AddDynamicArguments(t.ID.String()).
|
|
WithRepo(gitRepo).
|
|
RunStdBytes(ctx)
|
|
if runErr != nil {
|
|
return nil, runErr
|
|
}
|
|
|
|
// FIXME: the "name" field is abused, here it is a full path
|
|
// FIXME: this ptree is not right, fortunately it isn't really used
|
|
return parseTreeEntries(stdout, t)
|
|
}
|
|
|
|
// ListEntriesRecursiveFast returns all entries of current tree recursively including all subtrees, no size
|
|
func (t *Tree) ListEntriesRecursiveFast(ctx context.Context, gitRepo *Repository) (Entries, error) {
|
|
return t.listEntriesRecursive(ctx, gitRepo, nil)
|
|
}
|
|
|
|
// ListEntriesRecursiveWithSize returns all entries of current tree recursively including all subtrees, with size
|
|
func (t *Tree) ListEntriesRecursiveWithSize(ctx context.Context, gitRepo *Repository) (Entries, error) {
|
|
return t.listEntriesRecursive(ctx, gitRepo, gitcmd.TrustedCmdArgs{"--long"})
|
|
}
|