code.gitea.io/gitea@v1.22.3/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/git" 12 "code.gitea.io/gitea/modules/gitrepo" 13 "code.gitea.io/gitea/modules/log" 14 "code.gitea.io/gitea/services/context" 15 ) 16 17 // ResolveRefOrSha resolve ref to sha if exist 18 func ResolveRefOrSha(ctx *context.APIContext, ref string) string { 19 if len(ref) == 0 { 20 ctx.Error(http.StatusBadRequest, "ref not given", nil) 21 return "" 22 } 23 24 sha := ref 25 // Search branches and tags 26 for _, refType := range []string{"heads", "tags"} { 27 refSHA, lastMethodName, err := searchRefCommitByType(ctx, refType, ref) 28 if err != nil { 29 ctx.Error(http.StatusInternalServerError, lastMethodName, err) 30 return "" 31 } 32 if refSHA != "" { 33 sha = refSHA 34 break 35 } 36 } 37 38 sha = MustConvertToSHA1(ctx, ctx.Repo, sha) 39 40 if ctx.Repo.GitRepo != nil { 41 err := ctx.Repo.GitRepo.AddLastCommitCache(ctx.Repo.Repository.GetCommitsCountCacheKey(ref, ref != sha), ctx.Repo.Repository.FullName(), sha) 42 if err != nil { 43 log.Error("Unable to get commits count for %s in %s. Error: %v", sha, ctx.Repo.Repository.FullName(), err) 44 } 45 } 46 47 return sha 48 } 49 50 // GetGitRefs return git references based on filter 51 func GetGitRefs(ctx *context.APIContext, filter string) ([]*git.Reference, string, error) { 52 if ctx.Repo.GitRepo == nil { 53 return nil, "", fmt.Errorf("no open git repo found in context") 54 } 55 if len(filter) > 0 { 56 filter = "refs/" + filter 57 } 58 refs, err := ctx.Repo.GitRepo.GetRefsFiltered(filter) 59 return refs, "GetRefsFiltered", err 60 } 61 62 func searchRefCommitByType(ctx *context.APIContext, refType, filter string) (string, string, error) { 63 refs, lastMethodName, err := GetGitRefs(ctx, refType+"/"+filter) // Search by type 64 if err != nil { 65 return "", lastMethodName, err 66 } 67 if len(refs) > 0 { 68 return refs[0].Object.String(), "", nil // Return found SHA 69 } 70 return "", "", nil 71 } 72 73 // ConvertToObjectID returns a full-length SHA1 from a potential ID string 74 func ConvertToObjectID(ctx gocontext.Context, repo *context.Repository, commitID string) (git.ObjectID, error) { 75 objectFormat := repo.GetObjectFormat() 76 if len(commitID) == objectFormat.FullLength() && objectFormat.IsValid(commitID) { 77 sha, err := git.NewIDFromString(commitID) 78 if err == nil { 79 return sha, nil 80 } 81 } 82 83 gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo.Repository) 84 if err != nil { 85 return objectFormat.EmptyObjectID(), fmt.Errorf("RepositoryFromContextOrOpen: %w", err) 86 } 87 defer closer.Close() 88 89 return gitRepo.ConvertToGitID(commitID) 90 } 91 92 // MustConvertToSHA1 returns a full-length SHA1 string from a potential ID string, or returns origin input if it can't convert to SHA1 93 func MustConvertToSHA1(ctx gocontext.Context, repo *context.Repository, commitID string) string { 94 sha, err := ConvertToObjectID(ctx, repo, commitID) 95 if err != nil { 96 return commitID 97 } 98 return sha.String() 99 }