1// Copyright 2020 The Gitea Authors. All rights reserved. 2// Use of this source code is governed by a MIT-style 3// license that can be found in the LICENSE file. 4 5//go:build !gogit 6// +build !gogit 7 8package git 9 10import ( 11 "bufio" 12 "errors" 13 "io" 14 "strings" 15 16 "code.gitea.io/gitea/modules/log" 17) 18 19// ResolveReference resolves a name to a reference 20func (repo *Repository) ResolveReference(name string) (string, error) { 21 stdout, err := NewCommandContext(repo.Ctx, "show-ref", "--hash", name).RunInDir(repo.Path) 22 if err != nil { 23 if strings.Contains(err.Error(), "not a valid ref") { 24 return "", ErrNotExist{name, ""} 25 } 26 return "", err 27 } 28 stdout = strings.TrimSpace(stdout) 29 if stdout == "" { 30 return "", ErrNotExist{name, ""} 31 } 32 33 return stdout, nil 34} 35 36// GetRefCommitID returns the last commit ID string of given reference (branch or tag). 37func (repo *Repository) GetRefCommitID(name string) (string, error) { 38 wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx) 39 defer cancel() 40 _, err := wr.Write([]byte(name + "\n")) 41 if err != nil { 42 return "", err 43 } 44 shaBs, _, _, err := ReadBatchLine(rd) 45 if IsErrNotExist(err) { 46 return "", ErrNotExist{name, ""} 47 } 48 49 return string(shaBs), nil 50} 51 52// SetReference sets the commit ID string of given reference (e.g. branch or tag). 53func (repo *Repository) SetReference(name, commitID string) error { 54 _, err := NewCommandContext(repo.Ctx, "update-ref", name, commitID).RunInDir(repo.Path) 55 return err 56} 57 58// RemoveReference removes the given reference (e.g. branch or tag). 59func (repo *Repository) RemoveReference(name string) error { 60 _, err := NewCommandContext(repo.Ctx, "update-ref", "--no-deref", "-d", name).RunInDir(repo.Path) 61 return err 62} 63 64// IsCommitExist returns true if given commit exists in current repository. 65func (repo *Repository) IsCommitExist(name string) bool { 66 _, err := NewCommandContext(repo.Ctx, "cat-file", "-e", name).RunInDir(repo.Path) 67 return err == nil 68} 69 70func (repo *Repository) getCommit(id SHA1) (*Commit, error) { 71 wr, rd, cancel := repo.CatFileBatch(repo.Ctx) 72 defer cancel() 73 74 _, _ = wr.Write([]byte(id.String() + "\n")) 75 76 return repo.getCommitFromBatchReader(rd, id) 77} 78 79func (repo *Repository) getCommitFromBatchReader(rd *bufio.Reader, id SHA1) (*Commit, error) { 80 _, typ, size, err := ReadBatchLine(rd) 81 if err != nil { 82 if errors.Is(err, io.EOF) || IsErrNotExist(err) { 83 return nil, ErrNotExist{ID: id.String()} 84 } 85 return nil, err 86 } 87 88 switch typ { 89 case "missing": 90 return nil, ErrNotExist{ID: id.String()} 91 case "tag": 92 // then we need to parse the tag 93 // and load the commit 94 data, err := io.ReadAll(io.LimitReader(rd, size)) 95 if err != nil { 96 return nil, err 97 } 98 _, err = rd.Discard(1) 99 if err != nil { 100 return nil, err 101 } 102 tag, err := parseTagData(data) 103 if err != nil { 104 return nil, err 105 } 106 107 commit, err := tag.Commit(repo) 108 if err != nil { 109 return nil, err 110 } 111 112 commit.CommitMessage = strings.TrimSpace(tag.Message) 113 commit.Author = tag.Tagger 114 commit.Signature = tag.Signature 115 116 return commit, nil 117 case "commit": 118 commit, err := CommitFromReader(repo, id, io.LimitReader(rd, size)) 119 if err != nil { 120 return nil, err 121 } 122 _, err = rd.Discard(1) 123 if err != nil { 124 return nil, err 125 } 126 127 return commit, nil 128 default: 129 log.Debug("Unknown typ: %s", typ) 130 _, err = rd.Discard(int(size) + 1) 131 if err != nil { 132 return nil, err 133 } 134 return nil, ErrNotExist{ 135 ID: id.String(), 136 } 137 } 138} 139 140// ConvertToSHA1 returns a Hash object from a potential ID string 141func (repo *Repository) ConvertToSHA1(commitID string) (SHA1, error) { 142 if len(commitID) == 40 && SHAPattern.MatchString(commitID) { 143 sha1, err := NewIDFromString(commitID) 144 if err == nil { 145 return sha1, nil 146 } 147 } 148 149 wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx) 150 defer cancel() 151 _, err := wr.Write([]byte(commitID + "\n")) 152 if err != nil { 153 return SHA1{}, err 154 } 155 sha, _, _, err := ReadBatchLine(rd) 156 if err != nil { 157 if IsErrNotExist(err) { 158 return SHA1{}, ErrNotExist{commitID, ""} 159 } 160 return SHA1{}, err 161 } 162 163 return MustIDFromString(string(sha)), nil 164} 165