code.gitea.io/gitea@v1.21.7/routers/api/v1/utils/git.go (about) 1 // Copyright 2021 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package utils 5 6 import ( 7 gocontext "context" 8 "fmt" 9 "net/http" 10 11 "code.gitea.io/gitea/modules/context" 12 "code.gitea.io/gitea/modules/git" 13 "code.gitea.io/gitea/modules/log" 14 ) 15 16 // ResolveRefOrSha resolve ref to sha if exist 17 func ResolveRefOrSha(ctx *context.APIContext, ref string) string { 18 if len(ref) == 0 { 19 ctx.Error(http.StatusBadRequest, "ref not given", nil) 20 return "" 21 } 22 23 sha := ref 24 // Search branches and tags 25 for _, refType := range []string{"heads", "tags"} { 26 refSHA, lastMethodName, err := searchRefCommitByType(ctx, refType, ref) 27 if err != nil { 28 ctx.Error(http.StatusInternalServerError, lastMethodName, err) 29 return "" 30 } 31 if refSHA != "" { 32 sha = refSHA 33 break 34 } 35 } 36 37 sha = MustConvertToSHA1(ctx, ctx.Repo, sha) 38 39 if ctx.Repo.GitRepo != nil { 40 err := ctx.Repo.GitRepo.AddLastCommitCache(ctx.Repo.Repository.GetCommitsCountCacheKey(ref, ref != sha), ctx.Repo.Repository.FullName(), sha) 41 if err != nil { 42 log.Error("Unable to get commits count for %s in %s. Error: %v", sha, ctx.Repo.Repository.FullName(), err) 43 } 44 } 45 46 return sha 47 } 48 49 // GetGitRefs return git references based on filter 50 func GetGitRefs(ctx *context.APIContext, filter string) ([]*git.Reference, string, error) { 51 if ctx.Repo.GitRepo == nil { 52 return nil, "", fmt.Errorf("no open git repo found in context") 53 } 54 if len(filter) > 0 { 55 filter = "refs/" + filter 56 } 57 refs, err := ctx.Repo.GitRepo.GetRefsFiltered(filter) 58 return refs, "GetRefsFiltered", err 59 } 60 61 func searchRefCommitByType(ctx *context.APIContext, refType, filter string) (string, string, error) { 62 refs, lastMethodName, err := GetGitRefs(ctx, refType+"/"+filter) // Search by type 63 if err != nil { 64 return "", lastMethodName, err 65 } 66 if len(refs) > 0 { 67 return refs[0].Object.String(), "", nil // Return found SHA 68 } 69 return "", "", nil 70 } 71 72 // ConvertToSHA1 returns a full-length SHA1 from a potential ID string 73 func ConvertToSHA1(ctx gocontext.Context, repo *context.Repository, commitID string) (git.SHA1, error) { 74 if len(commitID) == git.SHAFullLength && git.IsValidSHAPattern(commitID) { 75 sha1, err := git.NewIDFromString(commitID) 76 if err == nil { 77 return sha1, nil 78 } 79 } 80 81 gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.Repository.RepoPath()) 82 if err != nil { 83 return git.SHA1{}, fmt.Errorf("RepositoryFromContextOrOpen: %w", err) 84 } 85 defer closer.Close() 86 87 return gitRepo.ConvertToSHA1(commitID) 88 } 89 90 // MustConvertToSHA1 returns a full-length SHA1 string from a potential ID string, or returns origin input if it can't convert to SHA1 91 func MustConvertToSHA1(ctx gocontext.Context, repo *context.Repository, commitID string) string { 92 sha, err := ConvertToSHA1(ctx, repo, commitID) 93 if err != nil { 94 return commitID 95 } 96 return sha.String() 97 }