Move push commits from models to modules/repository (#9370)
* Move push commits from models to modules/repository * fix test * fix test * fix test * fix test * fix test Co-authored-by: zeripath <art27@cantab.net>
This commit is contained in:
		
							parent
							
								
									384c2b342e
								
							
						
					
					
						commit
						99d869fa63
					
				
					 20 changed files with 482 additions and 436 deletions
				
			
		
							
								
								
									
										126
									
								
								models/action.go
									
									
									
									
									
								
							
							
						
						
									
										126
									
								
								models/action.go
									
									
									
									
									
								
							|  | @ -13,10 +13,8 @@ import ( | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"code.gitea.io/gitea/modules/base" | 	"code.gitea.io/gitea/modules/base" | ||||||
| 	"code.gitea.io/gitea/modules/git" |  | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" |  | ||||||
| 	"code.gitea.io/gitea/modules/timeutil" | 	"code.gitea.io/gitea/modules/timeutil" | ||||||
| 
 | 
 | ||||||
| 	"github.com/unknwon/com" | 	"github.com/unknwon/com" | ||||||
|  | @ -284,130 +282,6 @@ func (a *Action) GetIssueContent() string { | ||||||
| 	return issue.Content | 	return issue.Content | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // 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 { |  | ||||||
| 	Len        int |  | ||||||
| 	Commits    []*PushCommit |  | ||||||
| 	CompareURL string |  | ||||||
| 
 |  | ||||||
| 	avatars    map[string]string |  | ||||||
| 	emailUsers map[string]*User |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // NewPushCommits creates a new PushCommits object.
 |  | ||||||
| func NewPushCommits() *PushCommits { |  | ||||||
| 	return &PushCommits{ |  | ||||||
| 		avatars:    make(map[string]string), |  | ||||||
| 		emailUsers: make(map[string]*User), |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // ToAPIPayloadCommits converts a PushCommits object to
 |  | ||||||
| // api.PayloadCommit format.
 |  | ||||||
| func (pc *PushCommits) ToAPIPayloadCommits(repoPath, repoLink string) ([]*api.PayloadCommit, error) { |  | ||||||
| 	commits := make([]*api.PayloadCommit, len(pc.Commits)) |  | ||||||
| 
 |  | ||||||
| 	if pc.emailUsers == nil { |  | ||||||
| 		pc.emailUsers = make(map[string]*User) |  | ||||||
| 	} |  | ||||||
| 	var err error |  | ||||||
| 	for i, commit := range pc.Commits { |  | ||||||
| 		authorUsername := "" |  | ||||||
| 		author, ok := pc.emailUsers[commit.AuthorEmail] |  | ||||||
| 		if !ok { |  | ||||||
| 			author, err = GetUserByEmail(commit.AuthorEmail) |  | ||||||
| 			if err == nil { |  | ||||||
| 				authorUsername = author.Name |  | ||||||
| 				pc.emailUsers[commit.AuthorEmail] = author |  | ||||||
| 			} |  | ||||||
| 		} else { |  | ||||||
| 			authorUsername = author.Name |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		committerUsername := "" |  | ||||||
| 		committer, ok := pc.emailUsers[commit.CommitterEmail] |  | ||||||
| 		if !ok { |  | ||||||
| 			committer, err = GetUserByEmail(commit.CommitterEmail) |  | ||||||
| 			if err == nil { |  | ||||||
| 				// TODO: check errors other than email not found.
 |  | ||||||
| 				committerUsername = committer.Name |  | ||||||
| 				pc.emailUsers[commit.CommitterEmail] = committer |  | ||||||
| 			} |  | ||||||
| 		} else { |  | ||||||
| 			committerUsername = committer.Name |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		fileStatus, err := git.GetCommitFileStatus(repoPath, commit.Sha1) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return nil, fmt.Errorf("FileStatus [commit_sha1: %s]: %v", commit.Sha1, err) |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		commits[i] = &api.PayloadCommit{ |  | ||||||
| 			ID:      commit.Sha1, |  | ||||||
| 			Message: commit.Message, |  | ||||||
| 			URL:     fmt.Sprintf("%s/commit/%s", repoLink, 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, |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return commits, 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(email string) string { |  | ||||||
| 	if pc.avatars == nil { |  | ||||||
| 		pc.avatars = make(map[string]string) |  | ||||||
| 	} |  | ||||||
| 	avatar, ok := pc.avatars[email] |  | ||||||
| 	if ok { |  | ||||||
| 		return avatar |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	u, ok := pc.emailUsers[email] |  | ||||||
| 	if !ok { |  | ||||||
| 		var err error |  | ||||||
| 		u, err = GetUserByEmail(email) |  | ||||||
| 		if err != nil { |  | ||||||
| 			pc.avatars[email] = base.AvatarLink(email) |  | ||||||
| 			if !IsErrUserNotExist(err) { |  | ||||||
| 				log.Error("GetUserByEmail: %v", err) |  | ||||||
| 				return "" |  | ||||||
| 			} |  | ||||||
| 		} else { |  | ||||||
| 			pc.emailUsers[email] = u |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	if u != nil { |  | ||||||
| 		pc.avatars[email] = u.RelAvatarLink() |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return pc.avatars[email] |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // GetFeedsOptions options for retrieving feeds
 | // GetFeedsOptions options for retrieving feeds
 | ||||||
| type GetFeedsOptions struct { | type GetFeedsOptions struct { | ||||||
| 	RequestedUser    *User | 	RequestedUser    *User | ||||||
|  |  | ||||||
|  | @ -27,106 +27,6 @@ func TestAction_GetRepoLink(t *testing.T) { | ||||||
| 	assert.Equal(t, expected, action.GetRepoLink()) | 	assert.Equal(t, expected, action.GetRepoLink()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestPushCommits_ToAPIPayloadCommits(t *testing.T) { |  | ||||||
| 	pushCommits := NewPushCommits() |  | ||||||
| 	pushCommits.Commits = []*PushCommit{ |  | ||||||
| 		{ |  | ||||||
| 			Sha1:           "69554a6", |  | ||||||
| 			CommitterEmail: "user2@example.com", |  | ||||||
| 			CommitterName:  "User2", |  | ||||||
| 			AuthorEmail:    "user2@example.com", |  | ||||||
| 			AuthorName:     "User2", |  | ||||||
| 			Message:        "not signed commit", |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			Sha1:           "27566bd", |  | ||||||
| 			CommitterEmail: "user2@example.com", |  | ||||||
| 			CommitterName:  "User2", |  | ||||||
| 			AuthorEmail:    "user2@example.com", |  | ||||||
| 			AuthorName:     "User2", |  | ||||||
| 			Message:        "good signed commit (with not yet validated email)", |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			Sha1:           "5099b81", |  | ||||||
| 			CommitterEmail: "user2@example.com", |  | ||||||
| 			CommitterName:  "User2", |  | ||||||
| 			AuthorEmail:    "user2@example.com", |  | ||||||
| 			AuthorName:     "User2", |  | ||||||
| 			Message:        "good signed commit", |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
| 	pushCommits.Len = len(pushCommits.Commits) |  | ||||||
| 
 |  | ||||||
| 	repo := AssertExistsAndLoadBean(t, &Repository{ID: 16}).(*Repository) |  | ||||||
| 	payloadCommits, err := pushCommits.ToAPIPayloadCommits(repo.RepoPath(), "/user2/repo16") |  | ||||||
| 	assert.NoError(t, err) |  | ||||||
| 	assert.EqualValues(t, 3, len(payloadCommits)) |  | ||||||
| 
 |  | ||||||
| 	assert.Equal(t, "69554a6", payloadCommits[0].ID) |  | ||||||
| 	assert.Equal(t, "not signed commit", payloadCommits[0].Message) |  | ||||||
| 	assert.Equal(t, "/user2/repo16/commit/69554a6", payloadCommits[0].URL) |  | ||||||
| 	assert.Equal(t, "User2", payloadCommits[0].Committer.Name) |  | ||||||
| 	assert.Equal(t, "user2", payloadCommits[0].Committer.UserName) |  | ||||||
| 	assert.Equal(t, "User2", payloadCommits[0].Author.Name) |  | ||||||
| 	assert.Equal(t, "user2", payloadCommits[0].Author.UserName) |  | ||||||
| 	assert.EqualValues(t, []string{}, payloadCommits[0].Added) |  | ||||||
| 	assert.EqualValues(t, []string{}, payloadCommits[0].Removed) |  | ||||||
| 	assert.EqualValues(t, []string{"readme.md"}, payloadCommits[0].Modified) |  | ||||||
| 
 |  | ||||||
| 	assert.Equal(t, "27566bd", payloadCommits[1].ID) |  | ||||||
| 	assert.Equal(t, "good signed commit (with not yet validated email)", payloadCommits[1].Message) |  | ||||||
| 	assert.Equal(t, "/user2/repo16/commit/27566bd", payloadCommits[1].URL) |  | ||||||
| 	assert.Equal(t, "User2", payloadCommits[1].Committer.Name) |  | ||||||
| 	assert.Equal(t, "user2", payloadCommits[1].Committer.UserName) |  | ||||||
| 	assert.Equal(t, "User2", payloadCommits[1].Author.Name) |  | ||||||
| 	assert.Equal(t, "user2", payloadCommits[1].Author.UserName) |  | ||||||
| 	assert.EqualValues(t, []string{}, payloadCommits[1].Added) |  | ||||||
| 	assert.EqualValues(t, []string{}, payloadCommits[1].Removed) |  | ||||||
| 	assert.EqualValues(t, []string{"readme.md"}, payloadCommits[1].Modified) |  | ||||||
| 
 |  | ||||||
| 	assert.Equal(t, "5099b81", payloadCommits[2].ID) |  | ||||||
| 	assert.Equal(t, "good signed commit", payloadCommits[2].Message) |  | ||||||
| 	assert.Equal(t, "/user2/repo16/commit/5099b81", payloadCommits[2].URL) |  | ||||||
| 	assert.Equal(t, "User2", payloadCommits[2].Committer.Name) |  | ||||||
| 	assert.Equal(t, "user2", payloadCommits[2].Committer.UserName) |  | ||||||
| 	assert.Equal(t, "User2", payloadCommits[2].Author.Name) |  | ||||||
| 	assert.Equal(t, "user2", payloadCommits[2].Author.UserName) |  | ||||||
| 	assert.EqualValues(t, []string{"readme.md"}, payloadCommits[2].Added) |  | ||||||
| 	assert.EqualValues(t, []string{}, payloadCommits[2].Removed) |  | ||||||
| 	assert.EqualValues(t, []string{}, payloadCommits[2].Modified) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func TestPushCommits_AvatarLink(t *testing.T) { |  | ||||||
| 	pushCommits := NewPushCommits() |  | ||||||
| 	pushCommits.Commits = []*PushCommit{ |  | ||||||
| 		{ |  | ||||||
| 			Sha1:           "abcdef1", |  | ||||||
| 			CommitterEmail: "user2@example.com", |  | ||||||
| 			CommitterName:  "User Two", |  | ||||||
| 			AuthorEmail:    "user4@example.com", |  | ||||||
| 			AuthorName:     "User Four", |  | ||||||
| 			Message:        "message1", |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			Sha1:           "abcdef2", |  | ||||||
| 			CommitterEmail: "user2@example.com", |  | ||||||
| 			CommitterName:  "User Two", |  | ||||||
| 			AuthorEmail:    "user2@example.com", |  | ||||||
| 			AuthorName:     "User Two", |  | ||||||
| 			Message:        "message2", |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
| 	pushCommits.Len = len(pushCommits.Commits) |  | ||||||
| 
 |  | ||||||
| 	assert.Equal(t, |  | ||||||
| 		"/suburl/user/avatar/user2/-1", |  | ||||||
| 		pushCommits.AvatarLink("user2@example.com")) |  | ||||||
| 
 |  | ||||||
| 	assert.Equal(t, |  | ||||||
| 		"https://secure.gravatar.com/avatar/19ade630b94e1e0535b3df7387434154?d=identicon", |  | ||||||
| 		pushCommits.AvatarLink("nonexistent@example.com")) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func TestGetFeeds(t *testing.T) { | func TestGetFeeds(t *testing.T) { | ||||||
| 	// test with an individual user
 | 	// test with an individual user
 | ||||||
| 	assert.NoError(t, PrepareTestDatabase()) | 	assert.NoError(t, PrepareTestDatabase()) | ||||||
|  |  | ||||||
|  | @ -5,7 +5,6 @@ | ||||||
| package models | package models | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"container/list" |  | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
|  | @ -27,33 +26,6 @@ const ( | ||||||
| 	EnvIsInternal   = "GITEA_INTERNAL_PUSH" | 	EnvIsInternal   = "GITEA_INTERNAL_PUSH" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // 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, |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // ListToPushCommits transforms a list.List to PushCommits type.
 |  | ||||||
| func ListToPushCommits(l *list.List) *PushCommits { |  | ||||||
| 	var commits []*PushCommit |  | ||||||
| 	var actEmail string |  | ||||||
| 	for e := l.Front(); e != nil; e = e.Next() { |  | ||||||
| 		commit := e.Value.(*git.Commit) |  | ||||||
| 		if actEmail == "" { |  | ||||||
| 			actEmail = commit.Committer.Email |  | ||||||
| 		} |  | ||||||
| 		commits = append(commits, CommitToPushCommit(commit)) |  | ||||||
| 	} |  | ||||||
| 	return &PushCommits{l.Len(), commits, "", make(map[string]string), make(map[string]*User)} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // PushUpdateAddDeleteTags updates a number of added and delete tags
 | // PushUpdateAddDeleteTags updates a number of added and delete tags
 | ||||||
| func PushUpdateAddDeleteTags(repo *Repository, gitRepo *git.Repository, addTags, delTags []string) error { | func PushUpdateAddDeleteTags(repo *Repository, gitRepo *git.Repository, addTags, delTags []string) error { | ||||||
| 	sess := x.NewSession() | 	sess := x.NewSession() | ||||||
|  | @ -258,75 +230,25 @@ func pushUpdateAddTags(e Engine, repo *Repository, gitRepo *git.Repository, tags | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // PushUpdateAddTag must be called for any push actions to add tag
 | // SaveOrUpdateTag must be called for any push actions to add tag
 | ||||||
| func PushUpdateAddTag(repo *Repository, gitRepo *git.Repository, tagName string) error { | func SaveOrUpdateTag(repo *Repository, newRel *Release) error { | ||||||
| 	rel, err := GetRelease(repo.ID, tagName) | 	rel, err := GetRelease(repo.ID, newRel.TagName) | ||||||
| 	if err != nil && !IsErrReleaseNotExist(err) { | 	if err != nil && !IsErrReleaseNotExist(err) { | ||||||
| 		return fmt.Errorf("GetRelease: %v", err) | 		return fmt.Errorf("GetRelease: %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	tag, err := gitRepo.GetTag(tagName) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return fmt.Errorf("GetTag: %v", err) |  | ||||||
| 	} |  | ||||||
| 	commit, err := tag.Commit() |  | ||||||
| 	if err != nil { |  | ||||||
| 		return fmt.Errorf("Commit: %v", err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	sig := tag.Tagger |  | ||||||
| 	if sig == nil { |  | ||||||
| 		sig = commit.Author |  | ||||||
| 	} |  | ||||||
| 	if sig == nil { |  | ||||||
| 		sig = commit.Committer |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	var author *User |  | ||||||
| 	var createdAt = time.Unix(1, 0) |  | ||||||
| 
 |  | ||||||
| 	if sig != nil { |  | ||||||
| 		author, err = GetUserByEmail(sig.Email) |  | ||||||
| 		if err != nil && !IsErrUserNotExist(err) { |  | ||||||
| 			return fmt.Errorf("GetUserByEmail: %v", err) |  | ||||||
| 		} |  | ||||||
| 		createdAt = sig.When |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	commitsCount, err := commit.CommitsCount() |  | ||||||
| 	if err != nil { |  | ||||||
| 		return fmt.Errorf("CommitsCount: %v", err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if rel == nil { | 	if rel == nil { | ||||||
| 		rel = &Release{ | 		rel = newRel | ||||||
| 			RepoID:       repo.ID, | 		if _, err = x.Insert(rel); err != nil { | ||||||
| 			Title:        "", |  | ||||||
| 			TagName:      tagName, |  | ||||||
| 			LowerTagName: strings.ToLower(tagName), |  | ||||||
| 			Target:       "", |  | ||||||
| 			Sha1:         commit.ID.String(), |  | ||||||
| 			NumCommits:   commitsCount, |  | ||||||
| 			Note:         "", |  | ||||||
| 			IsDraft:      false, |  | ||||||
| 			IsPrerelease: false, |  | ||||||
| 			IsTag:        true, |  | ||||||
| 			CreatedUnix:  timeutil.TimeStamp(createdAt.Unix()), |  | ||||||
| 		} |  | ||||||
| 		if author != nil { |  | ||||||
| 			rel.PublisherID = author.ID |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if _, err = x.InsertOne(rel); err != nil { |  | ||||||
| 			return fmt.Errorf("InsertOne: %v", err) | 			return fmt.Errorf("InsertOne: %v", err) | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		rel.Sha1 = commit.ID.String() | 		rel.Sha1 = newRel.Sha1 | ||||||
| 		rel.CreatedUnix = timeutil.TimeStamp(createdAt.Unix()) | 		rel.CreatedUnix = newRel.CreatedUnix | ||||||
| 		rel.NumCommits = commitsCount | 		rel.NumCommits = newRel.NumCommits | ||||||
| 		rel.IsDraft = false | 		rel.IsDraft = false | ||||||
| 		if rel.IsTag && author != nil { | 		if rel.IsTag && newRel.PublisherID > 0 { | ||||||
| 			rel.PublisherID = author.ID | 			rel.PublisherID = newRel.PublisherID | ||||||
| 		} | 		} | ||||||
| 		if _, err = x.ID(rel.ID).AllCols().Update(rel); err != nil { | 		if _, err = x.ID(rel.ID).AllCols().Update(rel); err != nil { | ||||||
| 			return fmt.Errorf("Update: %v", err) | 			return fmt.Errorf("Update: %v", err) | ||||||
|  |  | ||||||
|  | @ -1,86 +0,0 @@ | ||||||
| // Copyright 2016 The Gitea Authors. All rights reserved.
 |  | ||||||
| // Use of this source code is governed by a MIT-style
 |  | ||||||
| // license that can be found in the LICENSE file.
 |  | ||||||
| 
 |  | ||||||
| package models |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"container/list" |  | ||||||
| 	"testing" |  | ||||||
| 	"time" |  | ||||||
| 
 |  | ||||||
| 	"code.gitea.io/gitea/modules/git" |  | ||||||
| 
 |  | ||||||
| 	"github.com/stretchr/testify/assert" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| func TestCommitToPushCommit(t *testing.T) { |  | ||||||
| 	now := time.Now() |  | ||||||
| 	sig := &git.Signature{ |  | ||||||
| 		Email: "example@example.com", |  | ||||||
| 		Name:  "John Doe", |  | ||||||
| 		When:  now, |  | ||||||
| 	} |  | ||||||
| 	const hexString = "0123456789abcdef0123456789abcdef01234567" |  | ||||||
| 	sha1, err := git.NewIDFromString(hexString) |  | ||||||
| 	assert.NoError(t, err) |  | ||||||
| 	pushCommit := CommitToPushCommit(&git.Commit{ |  | ||||||
| 		ID:            sha1, |  | ||||||
| 		Author:        sig, |  | ||||||
| 		Committer:     sig, |  | ||||||
| 		CommitMessage: "Commit Message", |  | ||||||
| 	}) |  | ||||||
| 	assert.Equal(t, hexString, pushCommit.Sha1) |  | ||||||
| 	assert.Equal(t, "Commit Message", pushCommit.Message) |  | ||||||
| 	assert.Equal(t, "example@example.com", pushCommit.AuthorEmail) |  | ||||||
| 	assert.Equal(t, "John Doe", pushCommit.AuthorName) |  | ||||||
| 	assert.Equal(t, "example@example.com", pushCommit.CommitterEmail) |  | ||||||
| 	assert.Equal(t, "John Doe", pushCommit.CommitterName) |  | ||||||
| 	assert.Equal(t, now, pushCommit.Timestamp) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func TestListToPushCommits(t *testing.T) { |  | ||||||
| 	now := time.Now() |  | ||||||
| 	sig := &git.Signature{ |  | ||||||
| 		Email: "example@example.com", |  | ||||||
| 		Name:  "John Doe", |  | ||||||
| 		When:  now, |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	const hexString1 = "0123456789abcdef0123456789abcdef01234567" |  | ||||||
| 	hash1, err := git.NewIDFromString(hexString1) |  | ||||||
| 	assert.NoError(t, err) |  | ||||||
| 	const hexString2 = "fedcba9876543210fedcba9876543210fedcba98" |  | ||||||
| 	hash2, err := git.NewIDFromString(hexString2) |  | ||||||
| 	assert.NoError(t, err) |  | ||||||
| 
 |  | ||||||
| 	l := list.New() |  | ||||||
| 	l.PushBack(&git.Commit{ |  | ||||||
| 		ID:            hash1, |  | ||||||
| 		Author:        sig, |  | ||||||
| 		Committer:     sig, |  | ||||||
| 		CommitMessage: "Message1", |  | ||||||
| 	}) |  | ||||||
| 	l.PushBack(&git.Commit{ |  | ||||||
| 		ID:            hash2, |  | ||||||
| 		Author:        sig, |  | ||||||
| 		Committer:     sig, |  | ||||||
| 		CommitMessage: "Message2", |  | ||||||
| 	}) |  | ||||||
| 
 |  | ||||||
| 	pushCommits := ListToPushCommits(l) |  | ||||||
| 	assert.Equal(t, 2, pushCommits.Len) |  | ||||||
| 	if assert.Len(t, pushCommits.Commits, 2) { |  | ||||||
| 		assert.Equal(t, "Message1", pushCommits.Commits[0].Message) |  | ||||||
| 		assert.Equal(t, hexString1, pushCommits.Commits[0].Sha1) |  | ||||||
| 		assert.Equal(t, "example@example.com", pushCommits.Commits[0].AuthorEmail) |  | ||||||
| 		assert.Equal(t, now, pushCommits.Commits[0].Timestamp) |  | ||||||
| 
 |  | ||||||
| 		assert.Equal(t, "Message2", pushCommits.Commits[1].Message) |  | ||||||
| 		assert.Equal(t, hexString2, pushCommits.Commits[1].Sha1) |  | ||||||
| 		assert.Equal(t, "example@example.com", pushCommits.Commits[1].AuthorEmail) |  | ||||||
| 		assert.Equal(t, now, pushCommits.Commits[1].Timestamp) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // TODO TestPushUpdate
 |  | ||||||
|  | @ -14,6 +14,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/git" | 	"code.gitea.io/gitea/modules/git" | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
| 	"code.gitea.io/gitea/modules/notification/base" | 	"code.gitea.io/gitea/modules/notification/base" | ||||||
|  | 	"code.gitea.io/gitea/modules/repository" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type actionNotifier struct { | type actionNotifier struct { | ||||||
|  | @ -266,7 +267,7 @@ func (*actionNotifier) NotifyMergePullRequest(pr *models.PullRequest, doer *mode | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (a *actionNotifier) NotifySyncPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *models.PushCommits) { | func (a *actionNotifier) NotifySyncPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *repository.PushCommits) { | ||||||
| 	data, err := json.Marshal(commits) | 	data, err := json.Marshal(commits) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Error("json.Marshal: %v", err) | 		log.Error("json.Marshal: %v", err) | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ package base | ||||||
| import ( | import ( | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
| 	"code.gitea.io/gitea/modules/git" | 	"code.gitea.io/gitea/modules/git" | ||||||
|  | 	"code.gitea.io/gitea/modules/repository" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // Notifier defines an interface to notify receiver
 | // Notifier defines an interface to notify receiver
 | ||||||
|  | @ -45,11 +46,11 @@ type Notifier interface { | ||||||
| 	NotifyUpdateRelease(doer *models.User, rel *models.Release) | 	NotifyUpdateRelease(doer *models.User, rel *models.Release) | ||||||
| 	NotifyDeleteRelease(doer *models.User, rel *models.Release) | 	NotifyDeleteRelease(doer *models.User, rel *models.Release) | ||||||
| 
 | 
 | ||||||
| 	NotifyPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *models.PushCommits) | 	NotifyPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *repository.PushCommits) | ||||||
| 	NotifyCreateRef(doer *models.User, repo *models.Repository, refType, refFullName string) | 	NotifyCreateRef(doer *models.User, repo *models.Repository, refType, refFullName string) | ||||||
| 	NotifyDeleteRef(doer *models.User, repo *models.Repository, refType, refFullName string) | 	NotifyDeleteRef(doer *models.User, repo *models.Repository, refType, refFullName string) | ||||||
| 
 | 
 | ||||||
| 	NotifySyncPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *models.PushCommits) | 	NotifySyncPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *repository.PushCommits) | ||||||
| 	NotifySyncCreateRef(doer *models.User, repo *models.Repository, refType, refFullName string) | 	NotifySyncCreateRef(doer *models.User, repo *models.Repository, refType, refFullName string) | ||||||
| 	NotifySyncDeleteRef(doer *models.User, repo *models.Repository, refType, refFullName string) | 	NotifySyncDeleteRef(doer *models.User, repo *models.Repository, refType, refFullName string) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ package base | ||||||
| import ( | import ( | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
| 	"code.gitea.io/gitea/modules/git" | 	"code.gitea.io/gitea/modules/git" | ||||||
|  | 	"code.gitea.io/gitea/modules/repository" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // NullNotifier implements a blank notifier
 | // NullNotifier implements a blank notifier
 | ||||||
|  | @ -116,7 +117,7 @@ func (*NullNotifier) NotifyMigrateRepository(doer *models.User, u *models.User, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // NotifyPushCommits notifies commits pushed to notifiers
 | // NotifyPushCommits notifies commits pushed to notifiers
 | ||||||
| func (*NullNotifier) NotifyPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *models.PushCommits) { | func (*NullNotifier) NotifyPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *repository.PushCommits) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // NotifyCreateRef notifies branch or tag creation to notifiers
 | // NotifyCreateRef notifies branch or tag creation to notifiers
 | ||||||
|  | @ -136,7 +137,7 @@ func (*NullNotifier) NotifyTransferRepository(doer *models.User, repo *models.Re | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // NotifySyncPushCommits places a place holder function
 | // NotifySyncPushCommits places a place holder function
 | ||||||
| func (*NullNotifier) NotifySyncPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *models.PushCommits) { | func (*NullNotifier) NotifySyncPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *repository.PushCommits) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // NotifySyncCreateRef places a place holder function
 | // NotifySyncCreateRef places a place holder function
 | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ import ( | ||||||
| 	issue_indexer "code.gitea.io/gitea/modules/indexer/issues" | 	issue_indexer "code.gitea.io/gitea/modules/indexer/issues" | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
| 	"code.gitea.io/gitea/modules/notification/base" | 	"code.gitea.io/gitea/modules/notification/base" | ||||||
|  | 	"code.gitea.io/gitea/modules/repository" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -117,7 +118,7 @@ func (r *indexerNotifier) NotifyMigrateRepository(doer *models.User, u *models.U | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (r *indexerNotifier) NotifyPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *models.PushCommits) { | func (r *indexerNotifier) NotifyPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *repository.PushCommits) { | ||||||
| 	if setting.Indexer.RepoIndexerEnabled && refName == repo.DefaultBranch { | 	if setting.Indexer.RepoIndexerEnabled && refName == repo.DefaultBranch { | ||||||
| 		code_indexer.UpdateRepoIndexer(repo) | 		code_indexer.UpdateRepoIndexer(repo) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/notification/mail" | 	"code.gitea.io/gitea/modules/notification/mail" | ||||||
| 	"code.gitea.io/gitea/modules/notification/ui" | 	"code.gitea.io/gitea/modules/notification/ui" | ||||||
| 	"code.gitea.io/gitea/modules/notification/webhook" | 	"code.gitea.io/gitea/modules/notification/webhook" | ||||||
|  | 	"code.gitea.io/gitea/modules/repository" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -215,7 +216,7 @@ func NotifyRenameRepository(doer *models.User, repo *models.Repository, oldName | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // NotifyPushCommits notifies commits pushed to notifiers
 | // NotifyPushCommits notifies commits pushed to notifiers
 | ||||||
| func NotifyPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *models.PushCommits) { | func NotifyPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *repository.PushCommits) { | ||||||
| 	for _, notifier := range notifiers { | 	for _, notifier := range notifiers { | ||||||
| 		notifier.NotifyPushCommits(pusher, repo, refName, oldCommitID, newCommitID, commits) | 		notifier.NotifyPushCommits(pusher, repo, refName, oldCommitID, newCommitID, commits) | ||||||
| 	} | 	} | ||||||
|  | @ -236,7 +237,7 @@ func NotifyDeleteRef(pusher *models.User, repo *models.Repository, refType, refF | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // NotifySyncPushCommits notifies commits pushed to notifiers
 | // NotifySyncPushCommits notifies commits pushed to notifiers
 | ||||||
| func NotifySyncPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *models.PushCommits) { | func NotifySyncPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *repository.PushCommits) { | ||||||
| 	for _, notifier := range notifiers { | 	for _, notifier := range notifiers { | ||||||
| 		notifier.NotifySyncPushCommits(pusher, repo, refName, oldCommitID, newCommitID, commits) | 		notifier.NotifySyncPushCommits(pusher, repo, refName, oldCommitID, newCommitID, commits) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/git" | 	"code.gitea.io/gitea/modules/git" | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
| 	"code.gitea.io/gitea/modules/notification/base" | 	"code.gitea.io/gitea/modules/notification/base" | ||||||
|  | 	"code.gitea.io/gitea/modules/repository" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
| 	webhook_module "code.gitea.io/gitea/modules/webhook" | 	webhook_module "code.gitea.io/gitea/modules/webhook" | ||||||
|  | @ -500,7 +501,7 @@ func (m *webhookNotifier) NotifyIssueChangeMilestone(doer *models.User, issue *m | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (m *webhookNotifier) NotifyPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *models.PushCommits) { | func (m *webhookNotifier) NotifyPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *repository.PushCommits) { | ||||||
| 	apiPusher := pusher.APIFormat() | 	apiPusher := pusher.APIFormat() | ||||||
| 	apiCommits, err := commits.ToAPIPayloadCommits(repo.RepoPath(), repo.HTMLURL()) | 	apiCommits, err := commits.ToAPIPayloadCommits(repo.RepoPath(), repo.HTMLURL()) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | @ -728,7 +729,7 @@ func (m *webhookNotifier) NotifyDeleteRelease(doer *models.User, rel *models.Rel | ||||||
| 	sendReleaseHook(doer, rel, api.HookReleaseDeleted) | 	sendReleaseHook(doer, rel, api.HookReleaseDeleted) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (m *webhookNotifier) NotifySyncPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *models.PushCommits) { | func (m *webhookNotifier) NotifySyncPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *repository.PushCommits) { | ||||||
| 	apiPusher := pusher.APIFormat() | 	apiPusher := pusher.APIFormat() | ||||||
| 	apiCommits, err := commits.ToAPIPayloadCommits(repo.RepoPath(), repo.HTMLURL()) | 	apiCommits, err := commits.ToAPIPayloadCommits(repo.RepoPath(), repo.HTMLURL()) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  |  | ||||||
|  | @ -15,6 +15,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
| 	"code.gitea.io/gitea/modules/notification" | 	"code.gitea.io/gitea/modules/notification" | ||||||
| 	"code.gitea.io/gitea/modules/references" | 	"code.gitea.io/gitea/modules/references" | ||||||
|  | 	"code.gitea.io/gitea/modules/repository" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -59,7 +60,7 @@ func changeIssueStatus(repo *models.Repository, issue *models.Issue, doer *model | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // UpdateIssuesCommit checks if issues are manipulated by commit message.
 | // UpdateIssuesCommit checks if issues are manipulated by commit message.
 | ||||||
| func UpdateIssuesCommit(doer *models.User, repo *models.Repository, commits []*models.PushCommit, branchName string) error { | func UpdateIssuesCommit(doer *models.User, repo *models.Repository, commits []*repository.PushCommit, branchName string) error { | ||||||
| 	// Commits are appended in the reverse order.
 | 	// Commits are appended in the reverse order.
 | ||||||
| 	for i := len(commits) - 1; i >= 0; i-- { | 	for i := len(commits) - 1; i >= 0; i-- { | ||||||
| 		c := commits[i] | 		c := commits[i] | ||||||
|  | @ -154,7 +155,7 @@ type CommitRepoActionOptions struct { | ||||||
| 	RefFullName string | 	RefFullName string | ||||||
| 	OldCommitID string | 	OldCommitID string | ||||||
| 	NewCommitID string | 	NewCommitID string | ||||||
| 	Commits     *models.PushCommits | 	Commits     *repository.PushCommits | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // CommitRepoAction adds new commit action to the repository, and prepare
 | // CommitRepoAction adds new commit action to the repository, and prepare
 | ||||||
|  | @ -216,10 +217,10 @@ func CommitRepoAction(optsList ...*CommitRepoActionOptions) error { | ||||||
| 			if opts.NewCommitID == git.EmptySHA { | 			if opts.NewCommitID == git.EmptySHA { | ||||||
| 				opType = models.ActionDeleteTag | 				opType = models.ActionDeleteTag | ||||||
| 			} | 			} | ||||||
| 			opts.Commits = &models.PushCommits{} | 			opts.Commits = &repository.PushCommits{} | ||||||
| 		} else if opts.NewCommitID == git.EmptySHA { | 		} else if opts.NewCommitID == git.EmptySHA { | ||||||
| 			opType = models.ActionDeleteBranch | 			opType = models.ActionDeleteBranch | ||||||
| 			opts.Commits = &models.PushCommits{} | 			opts.Commits = &repository.PushCommits{} | ||||||
| 		} else { | 		} else { | ||||||
| 			// if not the first commit, set the compare URL.
 | 			// if not the first commit, set the compare URL.
 | ||||||
| 			if opts.OldCommitID == git.EmptySHA { | 			if opts.OldCommitID == git.EmptySHA { | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ import ( | ||||||
| 
 | 
 | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
| 	"code.gitea.io/gitea/modules/git" | 	"code.gitea.io/gitea/modules/git" | ||||||
|  | 	"code.gitea.io/gitea/modules/repository" | ||||||
| 
 | 
 | ||||||
| 	"github.com/stretchr/testify/assert" | 	"github.com/stretchr/testify/assert" | ||||||
| ) | ) | ||||||
|  | @ -34,8 +35,8 @@ func TestCommitRepoAction(t *testing.T) { | ||||||
| 				RefFullName: "refName", | 				RefFullName: "refName", | ||||||
| 				OldCommitID: "oldCommitID", | 				OldCommitID: "oldCommitID", | ||||||
| 				NewCommitID: "newCommitID", | 				NewCommitID: "newCommitID", | ||||||
| 				Commits: &models.PushCommits{ | 				Commits: &repository.PushCommits{ | ||||||
| 					Commits: []*models.PushCommit{ | 					Commits: []*repository.PushCommit{ | ||||||
| 						{ | 						{ | ||||||
| 							Sha1:           "69554a6", | 							Sha1:           "69554a6", | ||||||
| 							CommitterEmail: "user2@example.com", | 							CommitterEmail: "user2@example.com", | ||||||
|  | @ -68,7 +69,7 @@ func TestCommitRepoAction(t *testing.T) { | ||||||
| 				RefFullName: git.TagPrefix + "v1.1", | 				RefFullName: git.TagPrefix + "v1.1", | ||||||
| 				OldCommitID: git.EmptySHA, | 				OldCommitID: git.EmptySHA, | ||||||
| 				NewCommitID: "newCommitID", | 				NewCommitID: "newCommitID", | ||||||
| 				Commits:     &models.PushCommits{}, | 				Commits:     &repository.PushCommits{}, | ||||||
| 			}, | 			}, | ||||||
| 			action: models.Action{ | 			action: models.Action{ | ||||||
| 				OpType:  models.ActionPushTag, | 				OpType:  models.ActionPushTag, | ||||||
|  | @ -82,7 +83,7 @@ func TestCommitRepoAction(t *testing.T) { | ||||||
| 				RefFullName: git.TagPrefix + "v1.1", | 				RefFullName: git.TagPrefix + "v1.1", | ||||||
| 				OldCommitID: "oldCommitID", | 				OldCommitID: "oldCommitID", | ||||||
| 				NewCommitID: git.EmptySHA, | 				NewCommitID: git.EmptySHA, | ||||||
| 				Commits:     &models.PushCommits{}, | 				Commits:     &repository.PushCommits{}, | ||||||
| 			}, | 			}, | ||||||
| 			action: models.Action{ | 			action: models.Action{ | ||||||
| 				OpType:  models.ActionDeleteTag, | 				OpType:  models.ActionDeleteTag, | ||||||
|  | @ -96,7 +97,7 @@ func TestCommitRepoAction(t *testing.T) { | ||||||
| 				RefFullName: git.BranchPrefix + "feature/1", | 				RefFullName: git.BranchPrefix + "feature/1", | ||||||
| 				OldCommitID: "oldCommitID", | 				OldCommitID: "oldCommitID", | ||||||
| 				NewCommitID: git.EmptySHA, | 				NewCommitID: git.EmptySHA, | ||||||
| 				Commits:     &models.PushCommits{}, | 				Commits:     &repository.PushCommits{}, | ||||||
| 			}, | 			}, | ||||||
| 			action: models.Action{ | 			action: models.Action{ | ||||||
| 				OpType:  models.ActionDeleteBranch, | 				OpType:  models.ActionDeleteBranch, | ||||||
|  | @ -127,7 +128,7 @@ func TestCommitRepoAction(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| func TestUpdateIssuesCommit(t *testing.T) { | func TestUpdateIssuesCommit(t *testing.T) { | ||||||
| 	assert.NoError(t, models.PrepareTestDatabase()) | 	assert.NoError(t, models.PrepareTestDatabase()) | ||||||
| 	pushCommits := []*models.PushCommit{ | 	pushCommits := []*repository.PushCommit{ | ||||||
| 		{ | 		{ | ||||||
| 			Sha1:           "abcdef1", | 			Sha1:           "abcdef1", | ||||||
| 			CommitterEmail: "user2@example.com", | 			CommitterEmail: "user2@example.com", | ||||||
|  | @ -174,7 +175,7 @@ func TestUpdateIssuesCommit(t *testing.T) { | ||||||
| 	models.CheckConsistencyFor(t, &models.Action{}) | 	models.CheckConsistencyFor(t, &models.Action{}) | ||||||
| 
 | 
 | ||||||
| 	// Test that push to a non-default branch closes no issue.
 | 	// Test that push to a non-default branch closes no issue.
 | ||||||
| 	pushCommits = []*models.PushCommit{ | 	pushCommits = []*repository.PushCommit{ | ||||||
| 		{ | 		{ | ||||||
| 			Sha1:           "abcdef1", | 			Sha1:           "abcdef1", | ||||||
| 			CommitterEmail: "user2@example.com", | 			CommitterEmail: "user2@example.com", | ||||||
|  | @ -203,7 +204,7 @@ func TestUpdateIssuesCommit(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| func TestUpdateIssuesCommit_Colon(t *testing.T) { | func TestUpdateIssuesCommit_Colon(t *testing.T) { | ||||||
| 	assert.NoError(t, models.PrepareTestDatabase()) | 	assert.NoError(t, models.PrepareTestDatabase()) | ||||||
| 	pushCommits := []*models.PushCommit{ | 	pushCommits := []*repository.PushCommit{ | ||||||
| 		{ | 		{ | ||||||
| 			Sha1:           "abcdef2", | 			Sha1:           "abcdef2", | ||||||
| 			CommitterEmail: "user2@example.com", | 			CommitterEmail: "user2@example.com", | ||||||
|  | @ -231,7 +232,7 @@ func TestUpdateIssuesCommit_Issue5957(t *testing.T) { | ||||||
| 	user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) | 	user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) | ||||||
| 
 | 
 | ||||||
| 	// Test that push to a non-default branch closes an issue.
 | 	// Test that push to a non-default branch closes an issue.
 | ||||||
| 	pushCommits := []*models.PushCommit{ | 	pushCommits := []*repository.PushCommit{ | ||||||
| 		{ | 		{ | ||||||
| 			Sha1:           "abcdef1", | 			Sha1:           "abcdef1", | ||||||
| 			CommitterEmail: "user2@example.com", | 			CommitterEmail: "user2@example.com", | ||||||
|  | @ -266,7 +267,7 @@ func TestUpdateIssuesCommit_AnotherRepo(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	// Test that a push to default branch closes issue in another repo
 | 	// Test that a push to default branch closes issue in another repo
 | ||||||
| 	// If the user also has push permissions to that repo
 | 	// If the user also has push permissions to that repo
 | ||||||
| 	pushCommits := []*models.PushCommit{ | 	pushCommits := []*repository.PushCommit{ | ||||||
| 		{ | 		{ | ||||||
| 			Sha1:           "abcdef1", | 			Sha1:           "abcdef1", | ||||||
| 			CommitterEmail: "user2@example.com", | 			CommitterEmail: "user2@example.com", | ||||||
|  | @ -301,7 +302,7 @@ func TestUpdateIssuesCommit_AnotherRepoNoPermission(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	// Test that a push with close reference *can not* close issue
 | 	// Test that a push with close reference *can not* close issue
 | ||||||
| 	// If the commiter doesn't have push rights in that repo
 | 	// If the commiter doesn't have push rights in that repo
 | ||||||
| 	pushCommits := []*models.PushCommit{ | 	pushCommits := []*repository.PushCommit{ | ||||||
| 		{ | 		{ | ||||||
| 			Sha1:           "abcdef3", | 			Sha1:           "abcdef3", | ||||||
| 			CommitterEmail: "user10@example.com", | 			CommitterEmail: "user10@example.com", | ||||||
|  |  | ||||||
|  | @ -18,6 +18,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/git" | 	"code.gitea.io/gitea/modules/git" | ||||||
| 	"code.gitea.io/gitea/modules/lfs" | 	"code.gitea.io/gitea/modules/lfs" | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
|  | 	"code.gitea.io/gitea/modules/repository" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| 	"code.gitea.io/gitea/modules/structs" | 	"code.gitea.io/gitea/modules/structs" | ||||||
| 	pull_service "code.gitea.io/gitea/services/pull" | 	pull_service "code.gitea.io/gitea/services/pull" | ||||||
|  | @ -549,7 +550,7 @@ func createCommitRepoActions(repo *models.Repository, gitRepo *git.Repository, o | ||||||
| 		if isNewRef && isDelRef { | 		if isNewRef && isDelRef { | ||||||
| 			return nil, fmt.Errorf("Old and new revisions are both %s", git.EmptySHA) | 			return nil, fmt.Errorf("Old and new revisions are both %s", git.EmptySHA) | ||||||
| 		} | 		} | ||||||
| 		var commits = &models.PushCommits{} | 		var commits = &repository.PushCommits{} | ||||||
| 		if strings.HasPrefix(opts.RefFullName, git.TagPrefix) { | 		if strings.HasPrefix(opts.RefFullName, git.TagPrefix) { | ||||||
| 			// If is tag reference
 | 			// If is tag reference
 | ||||||
| 			tagName := opts.RefFullName[len(git.TagPrefix):] | 			tagName := opts.RefFullName[len(git.TagPrefix):] | ||||||
|  | @ -584,7 +585,7 @@ func createCommitRepoActions(repo *models.Repository, gitRepo *git.Repository, o | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			commits = models.ListToPushCommits(l) | 			commits = repository.ListToPushCommits(l) | ||||||
| 		} | 		} | ||||||
| 		actions = append(actions, &CommitRepoActionOptions{ | 		actions = append(actions, &CommitRepoActionOptions{ | ||||||
| 			PusherName:  opts.PusherName, | 			PusherName:  opts.PusherName, | ||||||
|  | @ -609,7 +610,7 @@ func createCommitRepoActionOption(repo *models.Repository, gitRepo *git.Reposito | ||||||
| 		return nil, fmt.Errorf("Old and new revisions are both %s", git.EmptySHA) | 		return nil, fmt.Errorf("Old and new revisions are both %s", git.EmptySHA) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	var commits = &models.PushCommits{} | 	var commits = &repository.PushCommits{} | ||||||
| 	if strings.HasPrefix(opts.RefFullName, git.TagPrefix) { | 	if strings.HasPrefix(opts.RefFullName, git.TagPrefix) { | ||||||
| 		// If is tag reference
 | 		// If is tag reference
 | ||||||
| 		tagName := opts.RefFullName[len(git.TagPrefix):] | 		tagName := opts.RefFullName[len(git.TagPrefix):] | ||||||
|  | @ -620,7 +621,7 @@ func createCommitRepoActionOption(repo *models.Repository, gitRepo *git.Reposito | ||||||
| 		} else { | 		} else { | ||||||
| 			// Clear cache for tag commit count
 | 			// Clear cache for tag commit count
 | ||||||
| 			cache.Remove(repo.GetCommitsCountCacheKey(tagName, true)) | 			cache.Remove(repo.GetCommitsCountCacheKey(tagName, true)) | ||||||
| 			if err := models.PushUpdateAddTag(repo, gitRepo, tagName); err != nil { | 			if err := repository.PushUpdateAddTag(repo, gitRepo, tagName); err != nil { | ||||||
| 				return nil, fmt.Errorf("PushUpdateAddTag: %v", err) | 				return nil, fmt.Errorf("PushUpdateAddTag: %v", err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -649,7 +650,7 @@ func createCommitRepoActionOption(repo *models.Repository, gitRepo *git.Reposito | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		commits = models.ListToPushCommits(l) | 		commits = repository.ListToPushCommits(l) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return &CommitRepoActionOptions{ | 	return &CommitRepoActionOptions{ | ||||||
|  |  | ||||||
							
								
								
									
										168
									
								
								modules/repository/commits.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								modules/repository/commits.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,168 @@ | ||||||
|  | // Copyright 2019 The Gitea Authors. All rights reserved.
 | ||||||
|  | // Use of this source code is governed by a MIT-style
 | ||||||
|  | // license that can be found in the LICENSE file.
 | ||||||
|  | 
 | ||||||
|  | package repository | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"container/list" | ||||||
|  | 	"fmt" | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
|  | 	"code.gitea.io/gitea/models" | ||||||
|  | 	"code.gitea.io/gitea/modules/base" | ||||||
|  | 	"code.gitea.io/gitea/modules/git" | ||||||
|  | 	"code.gitea.io/gitea/modules/log" | ||||||
|  | 	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 { | ||||||
|  | 	Len        int | ||||||
|  | 	Commits    []*PushCommit | ||||||
|  | 	CompareURL string | ||||||
|  | 
 | ||||||
|  | 	avatars    map[string]string | ||||||
|  | 	emailUsers map[string]*models.User | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewPushCommits creates a new PushCommits object.
 | ||||||
|  | func NewPushCommits() *PushCommits { | ||||||
|  | 	return &PushCommits{ | ||||||
|  | 		avatars:    make(map[string]string), | ||||||
|  | 		emailUsers: make(map[string]*models.User), | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ToAPIPayloadCommits converts a PushCommits object to
 | ||||||
|  | // api.PayloadCommit format.
 | ||||||
|  | func (pc *PushCommits) ToAPIPayloadCommits(repoPath, repoLink string) ([]*api.PayloadCommit, error) { | ||||||
|  | 	commits := make([]*api.PayloadCommit, len(pc.Commits)) | ||||||
|  | 
 | ||||||
|  | 	if pc.emailUsers == nil { | ||||||
|  | 		pc.emailUsers = make(map[string]*models.User) | ||||||
|  | 	} | ||||||
|  | 	var err error | ||||||
|  | 	for i, commit := range pc.Commits { | ||||||
|  | 		authorUsername := "" | ||||||
|  | 		author, ok := pc.emailUsers[commit.AuthorEmail] | ||||||
|  | 		if !ok { | ||||||
|  | 			author, err = models.GetUserByEmail(commit.AuthorEmail) | ||||||
|  | 			if err == nil { | ||||||
|  | 				authorUsername = author.Name | ||||||
|  | 				pc.emailUsers[commit.AuthorEmail] = author | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			authorUsername = author.Name | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		committerUsername := "" | ||||||
|  | 		committer, ok := pc.emailUsers[commit.CommitterEmail] | ||||||
|  | 		if !ok { | ||||||
|  | 			committer, err = models.GetUserByEmail(commit.CommitterEmail) | ||||||
|  | 			if err == nil { | ||||||
|  | 				// TODO: check errors other than email not found.
 | ||||||
|  | 				committerUsername = committer.Name | ||||||
|  | 				pc.emailUsers[commit.CommitterEmail] = committer | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			committerUsername = committer.Name | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		fileStatus, err := git.GetCommitFileStatus(repoPath, commit.Sha1) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, fmt.Errorf("FileStatus [commit_sha1: %s]: %v", commit.Sha1, err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		commits[i] = &api.PayloadCommit{ | ||||||
|  | 			ID:      commit.Sha1, | ||||||
|  | 			Message: commit.Message, | ||||||
|  | 			URL:     fmt.Sprintf("%s/commit/%s", repoLink, 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, | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return commits, 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(email string) string { | ||||||
|  | 	if pc.avatars == nil { | ||||||
|  | 		pc.avatars = make(map[string]string) | ||||||
|  | 	} | ||||||
|  | 	avatar, ok := pc.avatars[email] | ||||||
|  | 	if ok { | ||||||
|  | 		return avatar | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	u, ok := pc.emailUsers[email] | ||||||
|  | 	if !ok { | ||||||
|  | 		var err error | ||||||
|  | 		u, err = models.GetUserByEmail(email) | ||||||
|  | 		if err != nil { | ||||||
|  | 			pc.avatars[email] = base.AvatarLink(email) | ||||||
|  | 			if !models.IsErrUserNotExist(err) { | ||||||
|  | 				log.Error("GetUserByEmail: %v", err) | ||||||
|  | 				return "" | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			pc.emailUsers[email] = u | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if u != nil { | ||||||
|  | 		pc.avatars[email] = u.RelAvatarLink() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return pc.avatars[email] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // 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, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ListToPushCommits transforms a list.List to PushCommits type.
 | ||||||
|  | func ListToPushCommits(l *list.List) *PushCommits { | ||||||
|  | 	var commits []*PushCommit | ||||||
|  | 	var actEmail string | ||||||
|  | 	for e := l.Front(); e != nil; e = e.Next() { | ||||||
|  | 		commit := e.Value.(*git.Commit) | ||||||
|  | 		if actEmail == "" { | ||||||
|  | 			actEmail = commit.Committer.Email | ||||||
|  | 		} | ||||||
|  | 		commits = append(commits, CommitToPushCommit(commit)) | ||||||
|  | 	} | ||||||
|  | 	return &PushCommits{l.Len(), commits, "", make(map[string]string), make(map[string]*models.User)} | ||||||
|  | } | ||||||
							
								
								
									
										190
									
								
								modules/repository/commits_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								modules/repository/commits_test.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,190 @@ | ||||||
|  | // Copyright 2019 The Gitea Authors. All rights reserved.
 | ||||||
|  | // Use of this source code is governed by a MIT-style
 | ||||||
|  | // license that can be found in the LICENSE file.
 | ||||||
|  | 
 | ||||||
|  | package repository | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"container/list" | ||||||
|  | 	"testing" | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
|  | 	"code.gitea.io/gitea/models" | ||||||
|  | 	"code.gitea.io/gitea/modules/git" | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestPushCommits_ToAPIPayloadCommits(t *testing.T) { | ||||||
|  | 	assert.NoError(t, models.PrepareTestDatabase()) | ||||||
|  | 
 | ||||||
|  | 	pushCommits := NewPushCommits() | ||||||
|  | 	pushCommits.Commits = []*PushCommit{ | ||||||
|  | 		{ | ||||||
|  | 			Sha1:           "69554a6", | ||||||
|  | 			CommitterEmail: "user2@example.com", | ||||||
|  | 			CommitterName:  "User2", | ||||||
|  | 			AuthorEmail:    "user2@example.com", | ||||||
|  | 			AuthorName:     "User2", | ||||||
|  | 			Message:        "not signed commit", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			Sha1:           "27566bd", | ||||||
|  | 			CommitterEmail: "user2@example.com", | ||||||
|  | 			CommitterName:  "User2", | ||||||
|  | 			AuthorEmail:    "user2@example.com", | ||||||
|  | 			AuthorName:     "User2", | ||||||
|  | 			Message:        "good signed commit (with not yet validated email)", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			Sha1:           "5099b81", | ||||||
|  | 			CommitterEmail: "user2@example.com", | ||||||
|  | 			CommitterName:  "User2", | ||||||
|  | 			AuthorEmail:    "user2@example.com", | ||||||
|  | 			AuthorName:     "User2", | ||||||
|  | 			Message:        "good signed commit", | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	pushCommits.Len = len(pushCommits.Commits) | ||||||
|  | 
 | ||||||
|  | 	repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 16}).(*models.Repository) | ||||||
|  | 	payloadCommits, err := pushCommits.ToAPIPayloadCommits(repo.RepoPath(), "/user2/repo16") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	assert.EqualValues(t, 3, len(payloadCommits)) | ||||||
|  | 
 | ||||||
|  | 	assert.Equal(t, "69554a6", payloadCommits[0].ID) | ||||||
|  | 	assert.Equal(t, "not signed commit", payloadCommits[0].Message) | ||||||
|  | 	assert.Equal(t, "/user2/repo16/commit/69554a6", payloadCommits[0].URL) | ||||||
|  | 	assert.Equal(t, "User2", payloadCommits[0].Committer.Name) | ||||||
|  | 	assert.Equal(t, "user2", payloadCommits[0].Committer.UserName) | ||||||
|  | 	assert.Equal(t, "User2", payloadCommits[0].Author.Name) | ||||||
|  | 	assert.Equal(t, "user2", payloadCommits[0].Author.UserName) | ||||||
|  | 	assert.EqualValues(t, []string{}, payloadCommits[0].Added) | ||||||
|  | 	assert.EqualValues(t, []string{}, payloadCommits[0].Removed) | ||||||
|  | 	assert.EqualValues(t, []string{"readme.md"}, payloadCommits[0].Modified) | ||||||
|  | 
 | ||||||
|  | 	assert.Equal(t, "27566bd", payloadCommits[1].ID) | ||||||
|  | 	assert.Equal(t, "good signed commit (with not yet validated email)", payloadCommits[1].Message) | ||||||
|  | 	assert.Equal(t, "/user2/repo16/commit/27566bd", payloadCommits[1].URL) | ||||||
|  | 	assert.Equal(t, "User2", payloadCommits[1].Committer.Name) | ||||||
|  | 	assert.Equal(t, "user2", payloadCommits[1].Committer.UserName) | ||||||
|  | 	assert.Equal(t, "User2", payloadCommits[1].Author.Name) | ||||||
|  | 	assert.Equal(t, "user2", payloadCommits[1].Author.UserName) | ||||||
|  | 	assert.EqualValues(t, []string{}, payloadCommits[1].Added) | ||||||
|  | 	assert.EqualValues(t, []string{}, payloadCommits[1].Removed) | ||||||
|  | 	assert.EqualValues(t, []string{"readme.md"}, payloadCommits[1].Modified) | ||||||
|  | 
 | ||||||
|  | 	assert.Equal(t, "5099b81", payloadCommits[2].ID) | ||||||
|  | 	assert.Equal(t, "good signed commit", payloadCommits[2].Message) | ||||||
|  | 	assert.Equal(t, "/user2/repo16/commit/5099b81", payloadCommits[2].URL) | ||||||
|  | 	assert.Equal(t, "User2", payloadCommits[2].Committer.Name) | ||||||
|  | 	assert.Equal(t, "user2", payloadCommits[2].Committer.UserName) | ||||||
|  | 	assert.Equal(t, "User2", payloadCommits[2].Author.Name) | ||||||
|  | 	assert.Equal(t, "user2", payloadCommits[2].Author.UserName) | ||||||
|  | 	assert.EqualValues(t, []string{"readme.md"}, payloadCommits[2].Added) | ||||||
|  | 	assert.EqualValues(t, []string{}, payloadCommits[2].Removed) | ||||||
|  | 	assert.EqualValues(t, []string{}, payloadCommits[2].Modified) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestPushCommits_AvatarLink(t *testing.T) { | ||||||
|  | 	assert.NoError(t, models.PrepareTestDatabase()) | ||||||
|  | 
 | ||||||
|  | 	pushCommits := NewPushCommits() | ||||||
|  | 	pushCommits.Commits = []*PushCommit{ | ||||||
|  | 		{ | ||||||
|  | 			Sha1:           "abcdef1", | ||||||
|  | 			CommitterEmail: "user2@example.com", | ||||||
|  | 			CommitterName:  "User Two", | ||||||
|  | 			AuthorEmail:    "user4@example.com", | ||||||
|  | 			AuthorName:     "User Four", | ||||||
|  | 			Message:        "message1", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			Sha1:           "abcdef2", | ||||||
|  | 			CommitterEmail: "user2@example.com", | ||||||
|  | 			CommitterName:  "User Two", | ||||||
|  | 			AuthorEmail:    "user2@example.com", | ||||||
|  | 			AuthorName:     "User Two", | ||||||
|  | 			Message:        "message2", | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	pushCommits.Len = len(pushCommits.Commits) | ||||||
|  | 
 | ||||||
|  | 	assert.Equal(t, | ||||||
|  | 		"/user/avatar/user2/-1", | ||||||
|  | 		pushCommits.AvatarLink("user2@example.com")) | ||||||
|  | 
 | ||||||
|  | 	assert.Equal(t, | ||||||
|  | 		"https://secure.gravatar.com/avatar/19ade630b94e1e0535b3df7387434154?d=identicon", | ||||||
|  | 		pushCommits.AvatarLink("nonexistent@example.com")) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestCommitToPushCommit(t *testing.T) { | ||||||
|  | 	now := time.Now() | ||||||
|  | 	sig := &git.Signature{ | ||||||
|  | 		Email: "example@example.com", | ||||||
|  | 		Name:  "John Doe", | ||||||
|  | 		When:  now, | ||||||
|  | 	} | ||||||
|  | 	const hexString = "0123456789abcdef0123456789abcdef01234567" | ||||||
|  | 	sha1, err := git.NewIDFromString(hexString) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	pushCommit := CommitToPushCommit(&git.Commit{ | ||||||
|  | 		ID:            sha1, | ||||||
|  | 		Author:        sig, | ||||||
|  | 		Committer:     sig, | ||||||
|  | 		CommitMessage: "Commit Message", | ||||||
|  | 	}) | ||||||
|  | 	assert.Equal(t, hexString, pushCommit.Sha1) | ||||||
|  | 	assert.Equal(t, "Commit Message", pushCommit.Message) | ||||||
|  | 	assert.Equal(t, "example@example.com", pushCommit.AuthorEmail) | ||||||
|  | 	assert.Equal(t, "John Doe", pushCommit.AuthorName) | ||||||
|  | 	assert.Equal(t, "example@example.com", pushCommit.CommitterEmail) | ||||||
|  | 	assert.Equal(t, "John Doe", pushCommit.CommitterName) | ||||||
|  | 	assert.Equal(t, now, pushCommit.Timestamp) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestListToPushCommits(t *testing.T) { | ||||||
|  | 	now := time.Now() | ||||||
|  | 	sig := &git.Signature{ | ||||||
|  | 		Email: "example@example.com", | ||||||
|  | 		Name:  "John Doe", | ||||||
|  | 		When:  now, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const hexString1 = "0123456789abcdef0123456789abcdef01234567" | ||||||
|  | 	hash1, err := git.NewIDFromString(hexString1) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	const hexString2 = "fedcba9876543210fedcba9876543210fedcba98" | ||||||
|  | 	hash2, err := git.NewIDFromString(hexString2) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 
 | ||||||
|  | 	l := list.New() | ||||||
|  | 	l.PushBack(&git.Commit{ | ||||||
|  | 		ID:            hash1, | ||||||
|  | 		Author:        sig, | ||||||
|  | 		Committer:     sig, | ||||||
|  | 		CommitMessage: "Message1", | ||||||
|  | 	}) | ||||||
|  | 	l.PushBack(&git.Commit{ | ||||||
|  | 		ID:            hash2, | ||||||
|  | 		Author:        sig, | ||||||
|  | 		Committer:     sig, | ||||||
|  | 		CommitMessage: "Message2", | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	pushCommits := ListToPushCommits(l) | ||||||
|  | 	assert.Equal(t, 2, pushCommits.Len) | ||||||
|  | 	if assert.Len(t, pushCommits.Commits, 2) { | ||||||
|  | 		assert.Equal(t, "Message1", pushCommits.Commits[0].Message) | ||||||
|  | 		assert.Equal(t, hexString1, pushCommits.Commits[0].Sha1) | ||||||
|  | 		assert.Equal(t, "example@example.com", pushCommits.Commits[0].AuthorEmail) | ||||||
|  | 		assert.Equal(t, now, pushCommits.Commits[0].Timestamp) | ||||||
|  | 
 | ||||||
|  | 		assert.Equal(t, "Message2", pushCommits.Commits[1].Message) | ||||||
|  | 		assert.Equal(t, hexString2, pushCommits.Commits[1].Sha1) | ||||||
|  | 		assert.Equal(t, "example@example.com", pushCommits.Commits[1].AuthorEmail) | ||||||
|  | 		assert.Equal(t, now, pushCommits.Commits[1].Timestamp) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // TODO TestPushUpdate
 | ||||||
							
								
								
									
										16
									
								
								modules/repository/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								modules/repository/main_test.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | ||||||
|  | // Copyright 2019 The Gitea Authors. All rights reserved.
 | ||||||
|  | // Use of this source code is governed by a MIT-style
 | ||||||
|  | // license that can be found in the LICENSE file.
 | ||||||
|  | 
 | ||||||
|  | package repository | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"path/filepath" | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"code.gitea.io/gitea/models" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestMain(m *testing.M) { | ||||||
|  | 	models.MainTest(m, filepath.Join("..", "..")) | ||||||
|  | } | ||||||
|  | @ -214,10 +214,61 @@ func SyncReleasesWithTags(repo *models.Repository, gitRepo *git.Repository) erro | ||||||
| 	} | 	} | ||||||
| 	for _, tagName := range tags { | 	for _, tagName := range tags { | ||||||
| 		if _, ok := existingRelTags[strings.ToLower(tagName)]; !ok { | 		if _, ok := existingRelTags[strings.ToLower(tagName)]; !ok { | ||||||
| 			if err := models.PushUpdateAddTag(repo, gitRepo, tagName); err != nil { | 			if err := PushUpdateAddTag(repo, gitRepo, tagName); err != nil { | ||||||
| 				return fmt.Errorf("pushUpdateAddTag: %s: %v", tagName, err) | 				return fmt.Errorf("pushUpdateAddTag: %v", err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // PushUpdateAddTag must be called for any push actions to add tag
 | ||||||
|  | func PushUpdateAddTag(repo *models.Repository, gitRepo *git.Repository, tagName string) error { | ||||||
|  | 	tag, err := gitRepo.GetTag(tagName) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("GetTag: %v", err) | ||||||
|  | 	} | ||||||
|  | 	commit, err := tag.Commit() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("Commit: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sig := tag.Tagger | ||||||
|  | 	if sig == nil { | ||||||
|  | 		sig = commit.Author | ||||||
|  | 	} | ||||||
|  | 	if sig == nil { | ||||||
|  | 		sig = commit.Committer | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var author *models.User | ||||||
|  | 	var createdAt = time.Unix(1, 0) | ||||||
|  | 
 | ||||||
|  | 	if sig != nil { | ||||||
|  | 		author, err = models.GetUserByEmail(sig.Email) | ||||||
|  | 		if err != nil && !models.IsErrUserNotExist(err) { | ||||||
|  | 			return fmt.Errorf("GetUserByEmail: %v", err) | ||||||
|  | 		} | ||||||
|  | 		createdAt = sig.When | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	commitsCount, err := commit.CommitsCount() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("CommitsCount: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var rel = models.Release{ | ||||||
|  | 		RepoID:       repo.ID, | ||||||
|  | 		TagName:      tagName, | ||||||
|  | 		LowerTagName: strings.ToLower(tagName), | ||||||
|  | 		Sha1:         commit.ID.String(), | ||||||
|  | 		NumCommits:   commitsCount, | ||||||
|  | 		CreatedUnix:  timeutil.TimeStamp(createdAt.Unix()), | ||||||
|  | 		IsTag:        true, | ||||||
|  | 	} | ||||||
|  | 	if author != nil { | ||||||
|  | 		rel.PublisherID = author.ID | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return models.SaveOrUpdateTag(repo, &rel) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -27,6 +27,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/base" | 	"code.gitea.io/gitea/modules/base" | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
| 	"code.gitea.io/gitea/modules/markup" | 	"code.gitea.io/gitea/modules/markup" | ||||||
|  | 	"code.gitea.io/gitea/modules/repository" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| 	"code.gitea.io/gitea/modules/timeutil" | 	"code.gitea.io/gitea/modules/timeutil" | ||||||
| 	"code.gitea.io/gitea/modules/util" | 	"code.gitea.io/gitea/modules/util" | ||||||
|  | @ -579,8 +580,8 @@ func ActionIcon(opType models.ActionType) string { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ActionContent2Commits converts action content to push commits
 | // ActionContent2Commits converts action content to push commits
 | ||||||
| func ActionContent2Commits(act Actioner) *models.PushCommits { | func ActionContent2Commits(act Actioner) *repository.PushCommits { | ||||||
| 	push := models.NewPushCommits() | 	push := repository.NewPushCommits() | ||||||
| 	if err := json.Unmarshal([]byte(act.GetContent()), push); err != nil { | 	if err := json.Unmarshal([]byte(act.GetContent()), push); err != nil { | ||||||
| 		log.Error("json.Unmarshal:\n%s\nERROR: %v", act.GetContent(), err) | 		log.Error("json.Unmarshal:\n%s\nERROR: %v", act.GetContent(), err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -403,7 +403,7 @@ func syncMirror(repoID string) { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		theCommits := models.ListToPushCommits(commits) | 		theCommits := repository.ListToPushCommits(commits) | ||||||
| 		if len(theCommits.Commits) > setting.UI.FeedMaxCommitNum { | 		if len(theCommits.Commits) > setting.UI.FeedMaxCommitNum { | ||||||
| 			theCommits.Commits = theCommits.Commits[:setting.UI.FeedMaxCommitNum] | 			theCommits.Commits = theCommits.Commits[:setting.UI.FeedMaxCommitNum] | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/git" | 	"code.gitea.io/gitea/modules/git" | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
| 	"code.gitea.io/gitea/modules/notification" | 	"code.gitea.io/gitea/modules/notification" | ||||||
|  | 	"code.gitea.io/gitea/modules/repository" | ||||||
| 	"code.gitea.io/gitea/modules/timeutil" | 	"code.gitea.io/gitea/modules/timeutil" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -43,7 +44,7 @@ func createTag(gitRepo *git.Repository, rel *models.Release) error { | ||||||
| 			} | 			} | ||||||
| 			notification.NotifyPushCommits( | 			notification.NotifyPushCommits( | ||||||
| 				rel.Publisher, rel.Repo, git.TagPrefix+rel.TagName, | 				rel.Publisher, rel.Repo, git.TagPrefix+rel.TagName, | ||||||
| 				git.EmptySHA, commit.ID.String(), models.NewPushCommits()) | 				git.EmptySHA, commit.ID.String(), repository.NewPushCommits()) | ||||||
| 			notification.NotifyCreateRef(rel.Publisher, rel.Repo, "tag", git.TagPrefix+rel.TagName) | 			notification.NotifyCreateRef(rel.Publisher, rel.Repo, "tag", git.TagPrefix+rel.TagName) | ||||||
| 		} | 		} | ||||||
| 		commit, err := gitRepo.GetTagCommit(rel.TagName) | 		commit, err := gitRepo.GetTagCommit(rel.TagName) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue