| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 | // Copyright 2014 The Gogs 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 databaseimport (	"context"	"fmt"	"os/exec"	"strings"	"github.com/gogs/git-module"	"github.com/pkg/errors")// 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.Committer.When,	}}func CommitsToPushCommits(commits []*git.Commit) *PushCommits {	if len(commits) == 0 {		return &PushCommits{}	}	pcs := make([]*PushCommit, len(commits))	for i := range commits {		pcs[i] = CommitToPushCommit(commits[i])	}	return &PushCommits{len(pcs), pcs, "", nil}}type PushUpdateOptions struct {	OldCommitID  string	NewCommitID  string	FullRefspec  string	PusherID     int64	PusherName   string	RepoUserName string	RepoName     string}// PushUpdate must be called for any push actions in order to// generates necessary push action history feeds.func PushUpdate(opts PushUpdateOptions) (err error) {	ctx := context.TODO()	isNewRef := strings.HasPrefix(opts.OldCommitID, git.EmptyID)	isDelRef := strings.HasPrefix(opts.NewCommitID, git.EmptyID)	if isNewRef && isDelRef {		return fmt.Errorf("both old and new revisions are %q", git.EmptyID)	}	repoPath := RepoPath(opts.RepoUserName, opts.RepoName)	gitUpdate := exec.Command("git", "update-server-info")	gitUpdate.Dir = repoPath	if err = gitUpdate.Run(); err != nil {		return fmt.Errorf("run 'git update-server-info': %v", err)	}	gitRepo, err := git.Open(repoPath)	if err != nil {		return fmt.Errorf("open repository: %v", err)	}	owner, err := Users.GetByUsername(ctx, opts.RepoUserName)	if err != nil {		return fmt.Errorf("GetUserByName: %v", err)	}	repo, err := GetRepositoryByName(owner.ID, opts.RepoName)	if err != nil {		return fmt.Errorf("GetRepositoryByName: %v", err)	}	if err = repo.UpdateSize(); err != nil {		return fmt.Errorf("UpdateSize: %v", err)	}	// Push tags	if strings.HasPrefix(opts.FullRefspec, git.RefsTags) {		err := Actions.PushTag(ctx,			PushTagOptions{				Owner:       owner,				Repo:        repo,				PusherName:  opts.PusherName,				RefFullName: opts.FullRefspec,				NewCommitID: opts.NewCommitID,			},		)		if err != nil {			return errors.Wrap(err, "create action for push tag")		}		return nil	}	var commits []*git.Commit	// Skip read parent commits when delete branch	if !isDelRef {		// Push new branch		newCommit, err := gitRepo.CatFileCommit(opts.NewCommitID)		if err != nil {			return fmt.Errorf("GetCommit [commit_id: %s]: %v", opts.NewCommitID, err)		}		if isNewRef {			commits, err = newCommit.Ancestors(git.LogOptions{MaxCount: 9})			if err != nil {				return fmt.Errorf("CommitsBeforeLimit [commit_id: %s]: %v", newCommit.ID, err)			}			commits = append([]*git.Commit{newCommit}, commits...)		} else {			commits, err = newCommit.CommitsAfter(opts.OldCommitID)			if err != nil {				return fmt.Errorf("CommitsBeforeUntil [commit_id: %s]: %v", opts.OldCommitID, err)			}		}	}	err = Actions.CommitRepo(ctx,		CommitRepoOptions{			Owner:       owner,			Repo:        repo,			PusherName:  opts.PusherName,			RefFullName: opts.FullRefspec,			OldCommitID: opts.OldCommitID,			NewCommitID: opts.NewCommitID,			Commits:     CommitsToPushCommits(commits),		},	)	if err != nil {		return errors.Wrap(err, "create action for commit push")	}	return nil}
 |