2014-04-27 11:05:13 +04:00
// 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.
2014-04-11 06:27:13 +04:00
package models
import (
"container/list"
2014-06-24 00:22:34 +04:00
"fmt"
2014-04-11 06:27:13 +04:00
"os/exec"
"strings"
2016-02-18 06:47:06 +03:00
git "github.com/gogits/git-module"
2015-12-10 04:46:05 +03:00
2014-06-20 09:14:54 +04:00
"github.com/gogits/gogs/modules/log"
2014-04-11 06:27:13 +04:00
)
2014-06-28 19:56:41 +04:00
type UpdateTask struct {
2015-10-24 10:36:47 +03:00
ID int64 ` xorm:"pk autoincr" `
UUID string ` xorm:"index" `
2014-06-28 19:56:41 +04:00
RefName string
2015-10-24 10:36:47 +03:00
OldCommitID string
NewCommitID string
2014-06-28 19:56:41 +04:00
}
func AddUpdateTask ( task * UpdateTask ) error {
_ , err := x . Insert ( task )
return err
}
2015-11-05 05:57:10 +03:00
// GetUpdateTaskByUUID returns update task by given UUID.
2015-10-24 10:36:47 +03:00
func GetUpdateTaskByUUID ( uuid string ) ( * UpdateTask , error ) {
2014-06-28 19:56:41 +04:00
task := & UpdateTask {
2015-10-24 10:36:47 +03:00
UUID : uuid ,
2014-06-28 19:56:41 +04:00
}
2015-10-24 10:36:47 +03:00
has , err := x . Get ( task )
2014-06-28 19:56:41 +04:00
if err != nil {
return nil , err
2015-10-24 10:36:47 +03:00
} else if ! has {
2015-11-05 05:57:10 +03:00
return nil , ErrUpdateTaskNotExist { uuid }
2014-06-28 19:56:41 +04:00
}
2015-10-24 10:36:47 +03:00
return task , nil
2014-06-28 19:56:41 +04:00
}
2015-10-24 10:36:47 +03:00
func DeleteUpdateTaskByUUID ( uuid string ) error {
_ , err := x . Delete ( & UpdateTask { UUID : uuid } )
2014-06-28 19:56:41 +04:00
return err
}
2015-12-10 04:46:05 +03:00
func ListToPushCommits ( l * list . List ) * PushCommits {
commits := make ( [ ] * PushCommit , 0 )
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 ,
& PushCommit { commit . ID . String ( ) ,
commit . Message ( ) ,
commit . Author . Email ,
commit . Author . Name ,
} )
}
return & PushCommits { l . Len ( ) , commits , "" , nil }
}
2016-02-18 06:47:06 +03:00
type PushUpdateOptions struct {
RefName string
OldCommitID string
NewCommitID 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 ) {
isNewRef := strings . HasPrefix ( opts . OldCommitID , "0000000" )
isDelRef := strings . HasPrefix ( opts . NewCommitID , "0000000" )
if isNewRef && isDelRef {
return fmt . Errorf ( "Old and new revisions both start with 000000" )
2014-04-11 06:27:13 +04:00
}
2016-02-18 06:47:06 +03:00
repoPath := RepoPath ( opts . RepoUserName , opts . RepoName )
2014-04-11 06:27:13 +04:00
gitUpdate := exec . Command ( "git" , "update-server-info" )
2016-02-18 06:47:06 +03:00
gitUpdate . Dir = repoPath
if err = gitUpdate . Run ( ) ; err != nil {
return fmt . Errorf ( "Fail to call 'git update-server-info': %v" , err )
}
2014-04-11 06:27:13 +04:00
2016-02-18 06:47:06 +03:00
if isDelRef {
log . GitLogger . Info ( "Reference '%s' has been deleted from '%s/%s' by %d" ,
opts . RefName , opts . RepoUserName , opts . RepoName , opts . PusherName )
2014-06-24 00:22:34 +04:00
return nil
2014-05-03 07:12:15 +04:00
}
2016-02-18 06:47:06 +03:00
gitRepo , err := git . OpenRepository ( repoPath )
2014-04-11 06:27:13 +04:00
if err != nil {
2016-02-18 06:47:06 +03:00
return fmt . Errorf ( "OpenRepository: %v" , err )
2014-04-11 06:27:13 +04:00
}
2016-02-18 06:47:06 +03:00
repoUser , err := GetUserByName ( opts . RepoUserName )
2014-05-03 09:37:49 +04:00
if err != nil {
2016-02-18 06:47:06 +03:00
return fmt . Errorf ( "GetUserByName: %v" , err )
2014-05-03 09:37:49 +04:00
}
2016-02-18 06:47:06 +03:00
repo , err := GetRepositoryByName ( repoUser . Id , opts . RepoName )
2014-04-11 06:27:13 +04:00
if err != nil {
2016-02-18 06:47:06 +03:00
return fmt . Errorf ( "GetRepositoryByName: %v" , err )
2014-04-11 06:27:13 +04:00
}
2014-07-26 08:24:27 +04:00
// Push tags.
2016-02-18 06:47:06 +03:00
if strings . HasPrefix ( opts . RefName , "refs/tags/" ) {
tag , err := gitRepo . GetTag ( git . RefEndName ( opts . RefName ) )
2014-06-28 10:55:33 +04:00
if err != nil {
2016-02-18 06:47:06 +03:00
return fmt . Errorf ( "gitRepo.GetTag: %v" , err )
2014-06-28 10:55:33 +04:00
}
2016-02-18 06:47:06 +03:00
// When tagger isn't available, fall back to get committer email.
2014-06-28 10:55:33 +04:00
var actEmail string
if tag . Tagger != nil {
actEmail = tag . Tagger . Email
} else {
cmt , err := tag . Commit ( )
if err != nil {
2016-02-18 06:47:06 +03:00
return fmt . Errorf ( "tag.Commit: %v" , err )
2014-06-28 10:55:33 +04:00
}
actEmail = cmt . Committer . Email
}
2015-11-14 01:10:25 +03:00
commit := & PushCommits { }
2016-02-18 06:47:06 +03:00
if err = CommitRepoAction ( opts . PusherID , repoUser . Id , opts . PusherName , actEmail ,
repo . ID , opts . RepoUserName , opts . RepoName , opts . RefName , commit , opts . OldCommitID , opts . NewCommitID ) ; err != nil {
return fmt . Errorf ( "CommitRepoAction (tag): %v" , err )
2014-06-28 10:55:33 +04:00
}
2014-06-28 11:00:03 +04:00
return err
2014-06-28 10:55:33 +04:00
}
2016-02-18 06:47:06 +03:00
newCommit , err := gitRepo . GetCommit ( opts . NewCommitID )
2014-06-28 19:56:41 +04:00
if err != nil {
2016-02-18 06:47:06 +03:00
return fmt . Errorf ( "gitRepo.GetCommit: %v" , err )
2014-06-28 19:56:41 +04:00
}
2014-10-11 05:40:51 +04:00
// Push new branch.
2014-06-28 19:56:41 +04:00
var l * list . List
2016-02-18 06:47:06 +03:00
if isNewRef {
2015-12-11 00:27:47 +03:00
l , err = newCommit . CommitsBeforeLimit ( 10 )
2014-06-28 19:56:41 +04:00
if err != nil {
2016-02-18 06:47:06 +03:00
return fmt . Errorf ( "newCommit.CommitsBeforeLimit: %v" , err )
2014-06-28 19:56:41 +04:00
}
} else {
2016-02-18 06:47:06 +03:00
l , err = newCommit . CommitsBeforeUntil ( opts . OldCommitID )
2014-06-28 19:56:41 +04:00
if err != nil {
2016-02-18 06:47:06 +03:00
return fmt . Errorf ( "newCommit.CommitsBeforeUntil: %v" , err )
2014-06-28 19:56:41 +04:00
}
}
2016-02-18 06:47:06 +03:00
if err = CommitRepoAction ( opts . PusherID , repoUser . Id , opts . PusherName , repoUser . Email ,
repo . ID , opts . RepoUserName , opts . RepoName , opts . RefName , ListToPushCommits ( l ) ,
opts . OldCommitID , opts . NewCommitID ) ; err != nil {
return fmt . Errorf ( "CommitRepoAction (branch): %v" , err )
2014-04-11 06:27:13 +04:00
}
2014-06-24 00:22:34 +04:00
return nil
2014-04-11 06:27:13 +04:00
}