4eb2a29910
The 4 functions are duplicated, especially as interface methods. I think we just need to keep `MustID` the only one and remove other 3. ``` MustID(b []byte) ObjectID MustIDFromString(s string) ObjectID NewID(b []byte) (ObjectID, error) NewIDFromString(s string) (ObjectID, error) ``` Introduced the new interfrace method `ComputeHash` which will replace the interface `HasherInterface`. Now we don't need to keep two interfaces. Reintroduced `git.NewIDFromString` and `git.MustIDFromString`. The new function will detect the hash length to decide which objectformat of it. If it's 40, then it's SHA1. If it's 64, then it's SHA256. This will be right if the commitID is a full one. So the parameter should be always a full commit id. @AdamMajer Please review.
98 lines
2.9 KiB
Go
98 lines
2.9 KiB
Go
// Copyright 2021 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package utils
|
|
|
|
import (
|
|
gocontext "context"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"code.gitea.io/gitea/modules/context"
|
|
"code.gitea.io/gitea/modules/git"
|
|
"code.gitea.io/gitea/modules/log"
|
|
)
|
|
|
|
// ResolveRefOrSha resolve ref to sha if exist
|
|
func ResolveRefOrSha(ctx *context.APIContext, ref string) string {
|
|
if len(ref) == 0 {
|
|
ctx.Error(http.StatusBadRequest, "ref not given", nil)
|
|
return ""
|
|
}
|
|
|
|
sha := ref
|
|
// Search branches and tags
|
|
for _, refType := range []string{"heads", "tags"} {
|
|
refSHA, lastMethodName, err := searchRefCommitByType(ctx, refType, ref)
|
|
if err != nil {
|
|
ctx.Error(http.StatusInternalServerError, lastMethodName, err)
|
|
return ""
|
|
}
|
|
if refSHA != "" {
|
|
sha = refSHA
|
|
break
|
|
}
|
|
}
|
|
|
|
sha = MustConvertToSHA1(ctx, ctx.Repo, sha)
|
|
|
|
if ctx.Repo.GitRepo != nil {
|
|
err := ctx.Repo.GitRepo.AddLastCommitCache(ctx.Repo.Repository.GetCommitsCountCacheKey(ref, ref != sha), ctx.Repo.Repository.FullName(), sha)
|
|
if err != nil {
|
|
log.Error("Unable to get commits count for %s in %s. Error: %v", sha, ctx.Repo.Repository.FullName(), err)
|
|
}
|
|
}
|
|
|
|
return sha
|
|
}
|
|
|
|
// GetGitRefs return git references based on filter
|
|
func GetGitRefs(ctx *context.APIContext, filter string) ([]*git.Reference, string, error) {
|
|
if ctx.Repo.GitRepo == nil {
|
|
return nil, "", fmt.Errorf("no open git repo found in context")
|
|
}
|
|
if len(filter) > 0 {
|
|
filter = "refs/" + filter
|
|
}
|
|
refs, err := ctx.Repo.GitRepo.GetRefsFiltered(filter)
|
|
return refs, "GetRefsFiltered", err
|
|
}
|
|
|
|
func searchRefCommitByType(ctx *context.APIContext, refType, filter string) (string, string, error) {
|
|
refs, lastMethodName, err := GetGitRefs(ctx, refType+"/"+filter) // Search by type
|
|
if err != nil {
|
|
return "", lastMethodName, err
|
|
}
|
|
if len(refs) > 0 {
|
|
return refs[0].Object.String(), "", nil // Return found SHA
|
|
}
|
|
return "", "", nil
|
|
}
|
|
|
|
// ConvertToObjectID returns a full-length SHA1 from a potential ID string
|
|
func ConvertToObjectID(ctx gocontext.Context, repo *context.Repository, commitID string) (git.ObjectID, error) {
|
|
objectFormat, _ := repo.GitRepo.GetObjectFormat()
|
|
if len(commitID) == objectFormat.FullLength() && objectFormat.IsValid(commitID) {
|
|
sha, err := git.NewIDFromString(commitID)
|
|
if err == nil {
|
|
return sha, nil
|
|
}
|
|
}
|
|
|
|
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.Repository.RepoPath())
|
|
if err != nil {
|
|
return objectFormat.EmptyObjectID(), fmt.Errorf("RepositoryFromContextOrOpen: %w", err)
|
|
}
|
|
defer closer.Close()
|
|
|
|
return gitRepo.ConvertToGitID(commitID)
|
|
}
|
|
|
|
// MustConvertToSHA1 returns a full-length SHA1 string from a potential ID string, or returns origin input if it can't convert to SHA1
|
|
func MustConvertToSHA1(ctx gocontext.Context, repo *context.Repository, commitID string) string {
|
|
sha, err := ConvertToObjectID(ctx, repo, commitID)
|
|
if err != nil {
|
|
return commitID
|
|
}
|
|
return sha.String()
|
|
}
|