mirror of
https://github.com/go-gitea/gitea.git
synced 2026-07-21 22:05:17 +02:00
before: gitrepo vs git packages after: git package fully handle all git operations by the way, use `WithRepo(repo)` instead of `WithDir(repo.Path)` to hide path details. benefits: 1. remove all unnecessary wrappers, developers no need to struggle with "which package should be used" 2. simplify code, RepositoryFacade can (will) be used everywhere, all "path" details are (will be) hidden
107 lines
2.8 KiB
Go
107 lines
2.8 KiB
Go
// Copyright 2015 The Gogs Authors. All rights reserved.
|
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
//go:build gogit
|
|
|
|
package git
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"gitea.dev/modules/git/gitcmd"
|
|
|
|
"github.com/go-git/go-git/v5/plumbing"
|
|
"github.com/go-git/go-git/v5/plumbing/hash"
|
|
"github.com/go-git/go-git/v5/plumbing/object"
|
|
)
|
|
|
|
// GetRefCommitID returns the last commit ID string of given reference.
|
|
func (repo *Repository) GetRefCommitID(_ context.Context, name string) (string, error) {
|
|
if plumbing.IsHash(name) {
|
|
return name, nil
|
|
}
|
|
refName := plumbing.ReferenceName(name)
|
|
if err := refName.Validate(); err != nil {
|
|
// Match the nogogit behavior: an unresolvable/invalid ref name
|
|
// is reported as not-existing rather than a generic validation error,
|
|
// so callers can rely on IsErrNotExist regardless of build tag.
|
|
return "", ErrNotExist{ID: name}
|
|
}
|
|
ref, err := repo.gogitRepo.Reference(refName, true)
|
|
if err != nil {
|
|
if err == plumbing.ErrReferenceNotFound {
|
|
return "", ErrNotExist{
|
|
ID: name,
|
|
}
|
|
}
|
|
return "", err
|
|
}
|
|
|
|
return ref.Hash().String(), nil
|
|
}
|
|
|
|
// ConvertToHash returns a Hash object from a potential ID string
|
|
func (repo *Repository) ConvertToGitID(ctx context.Context, commitID string) (ObjectID, error) {
|
|
objectFormat, err := repo.GetObjectFormat(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(commitID) == hash.HexSize && objectFormat.IsValid(commitID) {
|
|
ID, err := NewIDFromString(commitID)
|
|
if err == nil {
|
|
return ID, nil
|
|
}
|
|
}
|
|
|
|
actualCommitID, _, err := gitcmd.NewCommand("rev-parse", "--verify").
|
|
AddDynamicArguments(commitID).
|
|
WithRepo(repo).
|
|
RunStdString(ctx)
|
|
actualCommitID = strings.TrimSpace(actualCommitID)
|
|
if err != nil {
|
|
if strings.Contains(err.Error(), "unknown revision or path") ||
|
|
strings.Contains(err.Error(), "fatal: Needed a single revision") {
|
|
return objectFormat.EmptyObjectID(), ErrNotExist{commitID, ""}
|
|
}
|
|
return objectFormat.EmptyObjectID(), err
|
|
}
|
|
|
|
return NewIDFromString(actualCommitID)
|
|
}
|
|
|
|
func (repo *Repository) getCommit(_ context.Context, id ObjectID) (*Commit, error) {
|
|
var tagObject *object.Tag
|
|
|
|
commitID := plumbing.Hash(id.RawValue())
|
|
gogitCommit, err := repo.gogitRepo.CommitObject(commitID)
|
|
if err == plumbing.ErrObjectNotFound {
|
|
tagObject, err = repo.gogitRepo.TagObject(commitID)
|
|
if err == plumbing.ErrObjectNotFound {
|
|
return nil, ErrNotExist{
|
|
ID: id.String(),
|
|
}
|
|
}
|
|
if err == nil {
|
|
gogitCommit, err = repo.gogitRepo.CommitObject(tagObject.Target)
|
|
}
|
|
// if we get a plumbing.ErrObjectNotFound here then the repository is broken and it should be 500
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
commit := convertCommit(gogitCommit)
|
|
|
|
tree, err := gogitCommit.Tree()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
commit.TreeID = ParseGogitHash(tree.Hash)
|
|
commit.Tree().resolvedGogitTreeObject = tree
|
|
|
|
return commit, nil
|
|
}
|