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]>
154 lines
4.4 KiB
Go
154 lines
4.4 KiB
Go
// Copyright 2026 Hanzo AI, Inc. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package repository
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/url"
|
|
"time"
|
|
|
|
repo_model "github.com/hanzoai/git/models/repo"
|
|
user_model "github.com/hanzoai/git/models/user"
|
|
"github.com/hanzoai/git/modules/git"
|
|
"github.com/hanzoai/git/modules/gitrepo"
|
|
api "github.com/hanzoai/git/modules/structs"
|
|
)
|
|
|
|
// PushCommit represents a commit in a push operation.
|
|
// This struct is marshaled as JSON (see ActionContent2Commits)
|
|
type PushCommit struct {
|
|
Sha1 string
|
|
Message string
|
|
AuthorEmail string
|
|
AuthorName string
|
|
CommitterEmail string
|
|
CommitterName string
|
|
Timestamp time.Time
|
|
}
|
|
|
|
// PushCommits represents list of commits in a push operation.
|
|
// This struct is marshaled as JSON (see ActionContent2Commits)
|
|
type PushCommits struct {
|
|
Commits []*PushCommit
|
|
HeadCommit *PushCommit
|
|
CompareURL string
|
|
Len int
|
|
}
|
|
|
|
// NewPushCommits creates a new PushCommits object.
|
|
func NewPushCommits() *PushCommits {
|
|
return &PushCommits{}
|
|
}
|
|
|
|
// ToAPIPayloadCommit converts a single PushCommit to an api.PayloadCommit object.
|
|
func ToAPIPayloadCommit(ctx context.Context, emailUsers map[string]*user_model.User, repo *repo_model.Repository, commit *PushCommit) (*api.PayloadCommit, error) {
|
|
var err error
|
|
authorUsername := ""
|
|
author, ok := emailUsers[commit.AuthorEmail]
|
|
if !ok {
|
|
author, err = user_model.GetUserByEmail(ctx, commit.AuthorEmail)
|
|
if err == nil {
|
|
authorUsername = author.Name
|
|
emailUsers[commit.AuthorEmail] = author
|
|
}
|
|
} else {
|
|
authorUsername = author.Name
|
|
}
|
|
|
|
committerUsername := ""
|
|
committer, ok := emailUsers[commit.CommitterEmail]
|
|
if !ok {
|
|
committer, err = user_model.GetUserByEmail(ctx, commit.CommitterEmail)
|
|
if err == nil {
|
|
// TODO: check errors other than email not found.
|
|
committerUsername = committer.Name
|
|
emailUsers[commit.CommitterEmail] = committer
|
|
}
|
|
} else {
|
|
committerUsername = committer.Name
|
|
}
|
|
|
|
fileStatus, err := gitrepo.GetCommitFileStatus(ctx, repo, commit.Sha1)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("FileStatus [commit_sha1: %s]: %w", commit.Sha1, err)
|
|
}
|
|
|
|
return &api.PayloadCommit{
|
|
ID: commit.Sha1,
|
|
Message: commit.Message,
|
|
URL: fmt.Sprintf("%s/commit/%s", repo.HTMLURL(), url.PathEscape(commit.Sha1)),
|
|
Author: &api.PayloadUser{
|
|
Name: commit.AuthorName,
|
|
Email: commit.AuthorEmail,
|
|
UserName: authorUsername,
|
|
},
|
|
Committer: &api.PayloadUser{
|
|
Name: commit.CommitterName,
|
|
Email: commit.CommitterEmail,
|
|
UserName: committerUsername,
|
|
},
|
|
Added: fileStatus.Added,
|
|
Removed: fileStatus.Removed,
|
|
Modified: fileStatus.Modified,
|
|
Timestamp: commit.Timestamp,
|
|
}, nil
|
|
}
|
|
|
|
// ToAPIPayloadCommits converts a PushCommits object to api.PayloadCommit format.
|
|
// It returns all converted commits and, if provided, the head commit or an error otherwise.
|
|
func (pc *PushCommits) ToAPIPayloadCommits(ctx context.Context, repo *repo_model.Repository) ([]*api.PayloadCommit, *api.PayloadCommit, error) {
|
|
commits := make([]*api.PayloadCommit, len(pc.Commits))
|
|
var headCommit *api.PayloadCommit
|
|
|
|
emailUsers := make(map[string]*user_model.User)
|
|
|
|
for i, commit := range pc.Commits {
|
|
apiCommit, err := ToAPIPayloadCommit(ctx, emailUsers, repo, commit)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
commits[i] = apiCommit
|
|
if pc.HeadCommit != nil && pc.HeadCommit.Sha1 == commits[i].ID {
|
|
headCommit = apiCommit
|
|
}
|
|
}
|
|
if pc.HeadCommit != nil && headCommit == nil {
|
|
var err error
|
|
headCommit, err = ToAPIPayloadCommit(ctx, emailUsers, repo, pc.HeadCommit)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
}
|
|
return commits, headCommit, nil
|
|
}
|
|
|
|
// CommitToPushCommit transforms a git.Commit to PushCommit type.
|
|
func CommitToPushCommit(commit *git.Commit) *PushCommit {
|
|
return &PushCommit{
|
|
Sha1: commit.ID.String(),
|
|
Message: commit.MessageUTF8(),
|
|
AuthorEmail: commit.Author.Email,
|
|
AuthorName: commit.Author.Name,
|
|
CommitterEmail: commit.Committer.Email,
|
|
CommitterName: commit.Committer.Name,
|
|
Timestamp: commit.Author.When,
|
|
}
|
|
}
|
|
|
|
// GitToPushCommits transforms a list of git.Commits to PushCommits type.
|
|
func GitToPushCommits(gitCommits []*git.Commit) *PushCommits {
|
|
commits := make([]*PushCommit, 0, len(gitCommits))
|
|
for _, commit := range gitCommits {
|
|
commits = append(commits, CommitToPushCommit(commit))
|
|
}
|
|
return &PushCommits{
|
|
Commits: commits,
|
|
HeadCommit: nil,
|
|
CompareURL: "",
|
|
Len: len(commits),
|
|
}
|
|
}
|