github.com/wrgl/wrgl@v0.14.0/pkg/ref/refs.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright © 2022 Wrangle Ltd 3 4 package ref 5 6 import ( 7 "bytes" 8 "encoding/hex" 9 "fmt" 10 "strings" 11 "time" 12 13 "github.com/google/uuid" 14 "github.com/wrgl/wrgl/pkg/objects" 15 ) 16 17 const ( 18 HeadPrefix = "heads/" 19 TagPrefix = "tags/" 20 RemoteRefPrefix = "remotes/" 21 TransactionRefPrefix = "txs/" 22 ) 23 24 func HeadRef(name string) string { 25 return HeadPrefix + name 26 } 27 28 func tagRef(name string) string { 29 return TagPrefix + name 30 } 31 32 func TransactionRef(tid, branch string) string { 33 return fmt.Sprintf("%s%s/%s", TransactionRefPrefix, tid, branch) 34 } 35 36 func RemoteRef(remote, name string) string { 37 return fmt.Sprintf("%s%s/%s", string(RemoteRefPrefix), remote, name) 38 } 39 40 func SaveFetchRef(s Store, name string, commit []byte, authorName, authorEmail, remote, message string) error { 41 return SaveRef(s, name, commit, authorName, authorEmail, "fetch", fmt.Sprintf("[from %s] %s", remote, message), nil) 42 } 43 44 func SaveRef(s Store, name string, commit []byte, authorName, authorEmail, action, message string, txid *uuid.UUID) error { 45 reflog := &Reflog{ 46 AuthorName: authorName, 47 AuthorEmail: authorEmail, 48 Action: action, 49 Message: message, 50 Time: time.Now(), 51 NewOID: commit, 52 Txid: txid, 53 } 54 if b, err := s.Get(name); err == nil { 55 reflog.OldOID = b 56 } 57 return s.SetWithLog(name, commit, reflog) 58 } 59 60 func FirstLine(s string) string { 61 i := bytes.IndexByte([]byte(s), '\n') 62 if i == -1 { 63 return s 64 } 65 return s[:i] 66 } 67 68 func CommitHead(s Store, name string, sum []byte, commit *objects.Commit, txid *uuid.UUID) error { 69 return SaveRef(s, HeadRef(name), sum, commit.AuthorName, commit.AuthorEmail, "commit", FirstLine(commit.Message), txid) 70 } 71 72 func CommitMerge(s Store, branch string, sum []byte, commit *objects.Commit) error { 73 parents := []string{} 74 for _, parent := range commit.Parents { 75 parents = append(parents, hex.EncodeToString(parent)[:7]) 76 } 77 return SaveRef(s, HeadRef(branch), sum, commit.AuthorName, commit.AuthorEmail, "merge", fmt.Sprintf( 78 "merge %s", strings.Join(parents, ", "), 79 ), nil) 80 } 81 82 func SaveTag(s Store, name string, sum []byte) error { 83 return s.Set(tagRef(name), sum) 84 } 85 86 func SaveRemoteRef(s Store, remote, name string, commit []byte, authorName, authorEmail, action, message string) error { 87 return SaveRef(s, RemoteRef(remote, name), commit, authorName, authorEmail, action, message, nil) 88 } 89 90 func SaveTransactionRef(s Store, tid uuid.UUID, branch string, sum []byte) error { 91 return s.Set(TransactionRef(tid.String(), branch), sum) 92 } 93 94 func GetRef(s Store, name string) ([]byte, error) { 95 return s.Get(name) 96 } 97 98 func GetHead(s Store, name string) ([]byte, error) { 99 return s.Get(HeadRef(name)) 100 } 101 102 func GetTag(s Store, name string) ([]byte, error) { 103 return s.Get(tagRef(name)) 104 } 105 106 func GetRemoteRef(s Store, remote, name string) ([]byte, error) { 107 return s.Get(RemoteRef(remote, name)) 108 } 109 110 func listRefs(s Store, prefix string) (map[string][]byte, error) { 111 result := map[string][]byte{} 112 m, err := s.Filter([]string{prefix}, nil) 113 if err != nil { 114 return nil, err 115 } 116 l := len(prefix) 117 for k, v := range m { 118 name := k[l:] 119 result[name] = v 120 } 121 return result, nil 122 } 123 124 func ListTransactionRefs(s Store, id uuid.UUID) (map[string][]byte, error) { 125 return listRefs(s, TransactionRef(id.String(), "")) 126 } 127 128 func ListHeads(s Store) (map[string][]byte, error) { 129 return listRefs(s, HeadPrefix) 130 } 131 132 func ListTags(s Store) (map[string][]byte, error) { 133 return listRefs(s, TagPrefix) 134 } 135 136 func ListRemoteRefs(s Store, remote string) (map[string][]byte, error) { 137 return listRefs(s, RemoteRef(remote, "")) 138 } 139 140 func ListAllRefs(s Store) (map[string][]byte, error) { 141 return s.Filter(nil, nil) 142 } 143 144 func ListLocalRefs(s Store, prefixes, notPrefixes []string) (map[string][]byte, error) { 145 notPrefixes = append(notPrefixes, RemoteRefPrefix) 146 m, err := s.Filter(prefixes, notPrefixes) 147 if err != nil { 148 return nil, err 149 } 150 return m, nil 151 } 152 153 func DeleteRef(s Store, name string) error { 154 return s.Delete(name) 155 } 156 157 func DeleteHead(s Store, name string) error { 158 return DeleteRef(s, "heads/"+name) 159 } 160 161 func DeleteTag(s Store, name string) error { 162 return s.Delete(tagRef(name)) 163 } 164 165 func DeleteRemoteRef(s Store, remote, name string) error { 166 return DeleteRef(s, fmt.Sprintf("remotes/%s/%s", remote, name)) 167 } 168 169 func DeleteAllRemoteRefs(s Store, remote string) error { 170 keys, err := s.FilterKey([]string{RemoteRef(remote, "")}, nil) 171 if err != nil { 172 return err 173 } 174 for _, b := range keys { 175 err = s.Delete(b) 176 if err != nil { 177 return err 178 } 179 } 180 return nil 181 } 182 183 func DeleteTransactionRefs(s Store, id uuid.UUID) error { 184 keys, err := s.FilterKey([]string{TransactionRef(id.String(), "")}, nil) 185 if err != nil { 186 return err 187 } 188 for _, b := range keys { 189 err = s.Delete(b) 190 if err != nil { 191 return err 192 } 193 } 194 return nil 195 } 196 197 func RenameRef(s Store, oldName, newName string) (sum []byte, err error) { 198 sum, err = s.Get(oldName) 199 if err != nil { 200 return 201 } 202 err = s.Rename(oldName, newName) 203 if err != nil { 204 return 205 } 206 return sum, nil 207 } 208 209 func CopyRef(s Store, srcName, dstName string) (sum []byte, err error) { 210 sum, err = s.Get(srcName) 211 if err != nil { 212 return 213 } 214 err = s.Copy(srcName, dstName) 215 if err != nil { 216 return 217 } 218 return sum, nil 219 } 220 221 func RenameAllRemoteRefs(s Store, oldRemote, newRemote string) error { 222 prefix := RemoteRef(oldRemote, "") 223 n := len(prefix) 224 keys, err := s.FilterKey([]string{prefix}, nil) 225 if err != nil { 226 return err 227 } 228 for _, k := range keys { 229 name := string(k[n:]) 230 err = s.Rename(RemoteRef(oldRemote, name), RemoteRef(newRemote, name)) 231 if err != nil { 232 return err 233 } 234 } 235 return nil 236 }