github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/git/repo_ref_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  	"bufio"
    12  	"io"
    13  	"strings"
    14  )
    15  
    16  // GetRefsFiltered returns all references of the repository that matches patterm exactly or starting with.
    17  func (repo *Repository) GetRefsFiltered(pattern string) ([]*Reference, error) {
    18  	stdoutReader, stdoutWriter := io.Pipe()
    19  	defer func() {
    20  		_ = stdoutReader.Close()
    21  		_ = stdoutWriter.Close()
    22  	}()
    23  
    24  	go func() {
    25  		stderrBuilder := &strings.Builder{}
    26  		err := NewCommand(repo.Ctx, "for-each-ref").Run(&RunOpts{
    27  			Dir:    repo.Path,
    28  			Stdout: stdoutWriter,
    29  			Stderr: stderrBuilder,
    30  		})
    31  		if err != nil {
    32  			_ = stdoutWriter.CloseWithError(ConcatenateError(err, stderrBuilder.String()))
    33  		} else {
    34  			_ = stdoutWriter.Close()
    35  		}
    36  	}()
    37  
    38  	refs := make([]*Reference, 0)
    39  	bufReader := bufio.NewReader(stdoutReader)
    40  	for {
    41  		// The output of for-each-ref is simply a list:
    42  		// <sha> SP <type> TAB <ref> LF
    43  		sha, err := bufReader.ReadString(' ')
    44  		if err == io.EOF {
    45  			break
    46  		}
    47  		if err != nil {
    48  			return nil, err
    49  		}
    50  		sha = sha[:len(sha)-1]
    51  
    52  		typ, err := bufReader.ReadString('\t')
    53  		if err == io.EOF {
    54  			// This should not happen, but we'll tolerate it
    55  			break
    56  		}
    57  		if err != nil {
    58  			return nil, err
    59  		}
    60  		typ = typ[:len(typ)-1]
    61  
    62  		refName, err := bufReader.ReadString('\n')
    63  		if err == io.EOF {
    64  			// This should not happen, but we'll tolerate it
    65  			break
    66  		}
    67  		if err != nil {
    68  			return nil, err
    69  		}
    70  		refName = refName[:len(refName)-1]
    71  
    72  		// refName cannot be HEAD but can be remotes or stash
    73  		if strings.HasPrefix(refName, RemotePrefix) || refName == "/refs/stash" {
    74  			continue
    75  		}
    76  
    77  		if pattern == "" || strings.HasPrefix(refName, pattern) {
    78  			r := &Reference{
    79  				Name:   refName,
    80  				Object: MustIDFromString(sha),
    81  				Type:   typ,
    82  				repo:   repo,
    83  			}
    84  			refs = append(refs, r)
    85  		}
    86  	}
    87  
    88  	return refs, nil
    89  }