123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- // Copyright 2019 The Gitea Authors. All rights reserved.
- // SPDX-License-Identifier: MIT
-
- package repository
-
- import (
- "context"
- "fmt"
- "net/url"
- "time"
-
- "code.gitea.io/gitea/models/avatars"
- user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/cache"
- "code.gitea.io/gitea/modules/git"
- "code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/setting"
- api "code.gitea.io/gitea/modules/structs"
- )
-
- // PushCommit represents a commit in a push operation.
- 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.
- 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 (pc *PushCommits) toAPIPayloadCommit(ctx context.Context, emailUsers map[string]*user_model.User, repoPath, repoLink string, 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 := git.GetCommitFileStatus(ctx, repoPath, 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", repoLink, 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, repoPath, repoLink string) ([]*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 := pc.toAPIPayloadCommit(ctx, emailUsers, repoPath, repoLink, 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 = pc.toAPIPayloadCommit(ctx, emailUsers, repoPath, repoLink, pc.HeadCommit)
- if err != nil {
- return nil, nil, err
- }
- }
- return commits, headCommit, nil
- }
-
- // AvatarLink tries to match user in database with e-mail
- // in order to show custom avatar, and falls back to general avatar link.
- func (pc *PushCommits) AvatarLink(ctx context.Context, email string) string {
- size := avatars.DefaultAvatarPixelSize * setting.Avatar.RenderedSizeFactor
-
- v, _ := cache.GetWithContextCache(ctx, "push_commits", email, func() (string, error) {
- u, err := user_model.GetUserByEmail(ctx, email)
- if err != nil {
- if !user_model.IsErrUserNotExist(err) {
- log.Error("GetUserByEmail: %v", err)
- return "", err
- }
- return avatars.GenerateEmailAvatarFastLink(ctx, email, size), nil
- }
- return u.AvatarLinkWithSize(ctx, size), nil
- })
-
- return v
- }
-
- // CommitToPushCommit transforms a git.Commit to PushCommit type.
- func CommitToPushCommit(commit *git.Commit) *PushCommit {
- return &PushCommit{
- Sha1: commit.ID.String(),
- Message: commit.Message(),
- 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),
- }
- }
|