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