first-commit
This commit is contained in:
175
modules/repository/commits.go
Normal file
175
modules/repository/commits.go
Normal file
@@ -0,0 +1,175 @@
|
||||
// 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"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/cachegroup"
|
||||
"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 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 := git.GetCommitFileStatus(ctx, repo.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", 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
|
||||
}
|
||||
|
||||
// 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, cachegroup.EmailAvatarLink, email, func(ctx context.Context, email string) (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),
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user