mirror of
https://github.com/hanzoai/forge.git
synced 2026-10-30 15:00:39 +00:00
Source files keep their SPDX-License-Identifier and Hanzo copyright line; the Gitea, Gogs and LFS Test Server copyrights they used to repeat now live once in NOTICE, alongside LICENSE. The header lint accepts any copyright line above the SPDX line, so it no longer demands an upstream one. Co-authored-by: Hanzo Dev <[email protected]>
105 lines
2.7 KiB
Go
105 lines
2.7 KiB
Go
// Copyright 2026 Hanzo AI, Inc. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
//go:build gogit
|
|
|
|
package git
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/hanzoai/git/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(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(commitID string) (ObjectID, error) {
|
|
objectFormat, err := repo.GetObjectFormat()
|
|
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).
|
|
WithDir(repo.Path).
|
|
RunStdString(repo.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(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
|
|
}
|