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]>
65 lines
2.1 KiB
Go
65 lines
2.1 KiB
Go
// Copyright 2026 Hanzo AI, Inc. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package gituser
|
|
|
|
import (
|
|
"context"
|
|
"net/url"
|
|
|
|
"github.com/hanzoai/git/models/user"
|
|
"github.com/hanzoai/git/modules/container"
|
|
"github.com/hanzoai/git/modules/git"
|
|
)
|
|
|
|
// CommitParticipant is one participant of a commit (its author or a co-author):
|
|
// a git identity, optionally matched to a user.
|
|
type CommitParticipant struct {
|
|
GitIdentity *git.CommitIdentity // git identity (name/email), never nil
|
|
User *user.User // matched user, nil if unmatched
|
|
}
|
|
|
|
// UserCommit represents a commit with matched of database "author" user.
|
|
type UserCommit struct {
|
|
GitCommit *git.Commit
|
|
AuthorUser *user.User
|
|
AvatarStackData *AvatarStackData
|
|
}
|
|
|
|
func RepoCommitSearchByEmailLink(repoLink string, ref git.RefName) string {
|
|
if curRefWebLinkPath := ref.RefWebLinkPath(); curRefWebLinkPath != "" {
|
|
return repoLink + "/commits/" + curRefWebLinkPath + "/search?q=" + url.QueryEscape("author:") + "{email}"
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetUserCommitsByGitCommits checks if authors' e-mails of commits are corresponding to users.
|
|
func GetUserCommitsByGitCommits(ctx context.Context, gitCommits []*git.Commit, repoLink string, currentRef git.RefName) ([]*UserCommit, error) {
|
|
userCommits := make([]*UserCommit, 0, len(gitCommits))
|
|
emailSet := make(container.Set[string])
|
|
for _, c := range gitCommits {
|
|
emailSet.Add(c.Author.Email)
|
|
emailSet.Add(c.Committer.Email)
|
|
for _, p := range c.AllParticipantIdentities() {
|
|
emailSet.Add(p.Email)
|
|
}
|
|
}
|
|
|
|
emailUserMap, err := user.GetUsersByEmails(ctx, emailSet.Values())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
searchByEmailLink := RepoCommitSearchByEmailLink(repoLink, currentRef)
|
|
for _, c := range gitCommits {
|
|
uc := &UserCommit{
|
|
AuthorUser: emailUserMap.GetByEmail(c.Author.Email), // FIXME: why GetUserCommitsByGitCommits uses "Author", but ParseCommitsWithSignature uses "Committer"?
|
|
GitCommit: c,
|
|
AvatarStackData: BuildAvatarStackData(ctx, c.AllParticipantIdentities(), emailUserMap),
|
|
}
|
|
uc.AvatarStackData.SearchByEmailLink = searchByEmailLink
|
|
userCommits = append(userCommits, uc)
|
|
}
|
|
return userCommits, nil
|
|
}
|