From db39e58a139ef8581b4b61d2d4a68b4e5324acdf Mon Sep 17 00:00:00 2001
From: Lunny Xiao <xiaolunwen@gmail.com>
Date: Fri, 11 Apr 2014 10:27:13 +0800
Subject: [PATCH] add actions for http push

---
 models/update.go     |  93 +++++++++++++++++++++++++++++++++
 routers/repo/http.go |  21 ++++++--
 serve.go             |   9 ++++
 update.go            | 122 ++++++++-----------------------------------
 4 files changed, 141 insertions(+), 104 deletions(-)
 create mode 100644 models/update.go

diff --git a/models/update.go b/models/update.go
new file mode 100644
index 0000000000..2ceac271a7
--- /dev/null
+++ b/models/update.go
@@ -0,0 +1,93 @@
+package models
+
+import (
+	"container/list"
+	"os/exec"
+	"strings"
+
+	"github.com/gogits/git"
+	"github.com/gogits/gogs/modules/base"
+	qlog "github.com/qiniu/log"
+)
+
+func Update(refName, oldCommitId, newCommitId, userName, repoName string, userId int64) {
+	isNew := strings.HasPrefix(oldCommitId, "0000000")
+	if isNew &&
+		strings.HasPrefix(newCommitId, "0000000") {
+		qlog.Fatal("old rev and new rev both 000000")
+	}
+
+	f := RepoPath(userName, repoName)
+
+	gitUpdate := exec.Command("git", "update-server-info")
+	gitUpdate.Dir = f
+	gitUpdate.Run()
+
+	repo, err := git.OpenRepository(f)
+	if err != nil {
+		qlog.Fatalf("runUpdate.Open repoId: %v", err)
+	}
+
+	newOid, err := git.NewOidFromString(newCommitId)
+	if err != nil {
+		qlog.Fatalf("runUpdate.Ref repoId:%v err: %v", newCommitId, err)
+	}
+
+	newCommit, err := repo.LookupCommit(newOid)
+	if err != nil {
+		qlog.Fatalf("runUpdate.Ref repoId: %v", err)
+	}
+
+	var l *list.List
+	// if a new branch
+	if isNew {
+		l, err = repo.CommitsBefore(newCommit.Id())
+		if err != nil {
+			qlog.Fatalf("Find CommitsBefore erro:", err)
+		}
+	} else {
+		oldOid, err := git.NewOidFromString(oldCommitId)
+		if err != nil {
+			qlog.Fatalf("runUpdate.Ref repoId: %v", err)
+		}
+
+		oldCommit, err := repo.LookupCommit(oldOid)
+		if err != nil {
+			qlog.Fatalf("runUpdate.Ref repoId: %v", err)
+		}
+		l = repo.CommitsBetween(newCommit, oldCommit)
+	}
+
+	if err != nil {
+		qlog.Fatalf("runUpdate.Commit repoId: %v", err)
+	}
+
+	repos, err := GetRepositoryByName(userId, repoName)
+	if err != nil {
+		qlog.Fatalf("runUpdate.GetRepositoryByName userId: %v", err)
+	}
+
+	commits := make([]*base.PushCommit, 0)
+	var maxCommits = 3
+	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,
+			&base.PushCommit{commit.Id().String(),
+				commit.Message(),
+				commit.Author.Email,
+				commit.Author.Name})
+		if len(commits) >= maxCommits {
+			break
+		}
+	}
+
+	//commits = append(commits, []string{lastCommit.Id().String(), lastCommit.Message()})
+	if err = CommitRepoAction(userId, userName, actEmail,
+		repos.Id, repoName, git.BranchName(refName), &base.PushCommits{l.Len(), commits}); err != nil {
+		qlog.Fatalf("runUpdate.models.CommitRepoAction: %v", err)
+	}
+}
diff --git a/routers/repo/http.go b/routers/repo/http.go
index 5aa3139f85..d15c66e022 100644
--- a/routers/repo/http.go
+++ b/routers/repo/http.go
@@ -1,6 +1,7 @@
 package repo
 
 import (
+	"bytes"
 	"fmt"
 	"io"
 	"io/ioutil"
@@ -54,6 +55,8 @@ func Http(ctx *middleware.Context, params martini.Params) {
 	// only public pull don't need auth
 	var askAuth = !(!repo.IsPrivate && isPull)
 
+	var authUser *models.User
+
 	// check access
 	if askAuth {
 		baHead := ctx.Req.Header.Get("Authorization")
@@ -76,7 +79,7 @@ func Http(ctx *middleware.Context, params martini.Params) {
 			return
 		}
 
-		authUser, err := models.GetUserByName(authUsername)
+		authUser, err = models.GetUserByName(authUsername)
 		if err != nil {
 			ctx.Handle(401, "no basic auth and digit auth", nil)
 			return
@@ -114,8 +117,20 @@ func Http(ctx *middleware.Context, params martini.Params) {
 	}
 
 	config := Config{base.RepoRootPath, "git", true, true, func(rpc string, input []byte) {
-		//fmt.Println("rpc:", rpc)
-		//fmt.Println("input:", string(input))
+		if rpc == "receive-pack" {
+			firstLine := bytes.IndexRune(input, '\n')
+			fmt.Println("firstLine", firstLine)
+			if firstLine > -1 {
+				fields := strings.Fields(string(input[:firstLine]))
+				if len(fields) > 3 {
+					oldCommitId := fields[0][4:]
+					newCommitId := fields[1]
+					refName := fields[2]
+
+					models.Update(refName, oldCommitId, newCommitId, username, reponame, authUser.Id)
+				}
+			}
+		}
 	}}
 
 	handler := HttpBackend(&config)
diff --git a/serve.go b/serve.go
index 3843da617e..882e8bb4f5 100644
--- a/serve.go
+++ b/serve.go
@@ -189,4 +189,13 @@ func runServ(k *cli.Context) {
 		println("execute command error:", err.Error())
 		qlog.Fatal("execute command error: " + err.Error())
 	}
+
+	//refName := os.Getenv("refName")
+	//oldCommitId := os.Getenv("oldCommitId")
+	//newCommitId := os.Getenv("newCommitId")
+
+	//qlog.Error("get envs:", refName, oldCommitId, newCommitId)
+
+	// update
+	//models.Update(refName, oldCommitId, newCommitId, repoUserName, repoName, user.Id)
 }
diff --git a/update.go b/update.go
index 141d6fe868..1db703ad99 100644
--- a/update.go
+++ b/update.go
@@ -5,19 +5,14 @@
 package main
 
 import (
-	"container/list"
 	"os"
-	"os/exec"
 	"path"
 	"strconv"
-	"strings"
 
 	"github.com/codegangsta/cli"
-	qlog "github.com/qiniu/log"
-
-	"github.com/gogits/git"
 	"github.com/gogits/gogs/models"
 	"github.com/gogits/gogs/modules/base"
+	qlog "github.com/qiniu/log"
 )
 
 var CmdUpdate = cli.Command{
@@ -42,100 +37,20 @@ func newUpdateLogger(execDir string) {
 	qlog.Info("Start logging update...")
 }
 
-func update(refName, oldCommitId, newCommitId string) {
-	isNew := strings.HasPrefix(oldCommitId, "0000000")
-	if isNew &&
-		strings.HasPrefix(newCommitId, "0000000") {
-		qlog.Fatal("old rev and new rev both 000000")
-	}
-
-	userName := os.Getenv("userName")
-	userId := os.Getenv("userId")
-	//repoId := os.Getenv("repoId")
-	repoName := os.Getenv("repoName")
-
-	f := models.RepoPath(userName, repoName)
-
-	gitUpdate := exec.Command("git", "update-server-info")
-	gitUpdate.Dir = f
-	gitUpdate.Run()
-
-	repo, err := git.OpenRepository(f)
-	if err != nil {
-		qlog.Fatalf("runUpdate.Open repoId: %v", err)
-	}
-
-	newOid, err := git.NewOidFromString(newCommitId)
-	if err != nil {
-		qlog.Fatalf("runUpdate.Ref repoId: %v", err)
-	}
-
-	newCommit, err := repo.LookupCommit(newOid)
-	if err != nil {
-		qlog.Fatalf("runUpdate.Ref repoId: %v", err)
-	}
-
-	var l *list.List
-	// if a new branch
-	if isNew {
-		l, err = repo.CommitsBefore(newCommit.Id())
-		if err != nil {
-			qlog.Fatalf("Find CommitsBefore erro:", err)
-		}
-	} else {
-		oldOid, err := git.NewOidFromString(oldCommitId)
-		if err != nil {
-			qlog.Fatalf("runUpdate.Ref repoId: %v", err)
-		}
-
-		oldCommit, err := repo.LookupCommit(oldOid)
-		if err != nil {
-			qlog.Fatalf("runUpdate.Ref repoId: %v", err)
-		}
-		l = repo.CommitsBetween(newCommit, oldCommit)
-	}
-
-	if err != nil {
-		qlog.Fatalf("runUpdate.Commit repoId: %v", err)
-	}
-
-	sUserId, err := strconv.Atoi(userId)
-	if err != nil {
-		qlog.Fatalf("runUpdate.Parse userId: %v", err)
-	}
-
-	repos, err := models.GetRepositoryByName(int64(sUserId), repoName)
-	if err != nil {
-		qlog.Fatalf("runUpdate.GetRepositoryByName userId: %v", err)
-	}
-
-	commits := make([]*base.PushCommit, 0)
-	var maxCommits = 3
-	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,
-			&base.PushCommit{commit.Id().String(),
-				commit.Message(),
-				commit.Author.Email,
-				commit.Author.Name})
-		if len(commits) >= maxCommits {
-			break
-		}
-	}
-
-	//commits = append(commits, []string{lastCommit.Id().String(), lastCommit.Message()})
-	if err = models.CommitRepoAction(int64(sUserId), userName, actEmail,
-		repos.Id, repoName, git.BranchName(refName), &base.PushCommits{l.Len(), commits}); err != nil {
-		qlog.Fatalf("runUpdate.models.CommitRepoAction: %v", err)
-	}
+func updateEnv(refName, oldCommitId, newCommitId string) {
+	os.Setenv("refName", refName)
+	os.Setenv("oldCommitId", oldCommitId)
+	os.Setenv("newCommitId", newCommitId)
+	qlog.Error("set envs:", refName, oldCommitId, newCommitId)
 }
 
 // for command: ./gogs update
 func runUpdate(c *cli.Context) {
+	cmd := os.Getenv("SSH_ORIGINAL_COMMAND")
+	if cmd == "" {
+		return
+	}
+
 	execDir, _ := base.ExecDir()
 	newUpdateLogger(execDir)
 
@@ -153,12 +68,17 @@ func runUpdate(c *cli.Context) {
 		qlog.Fatal("received less 3 parameters")
 	}
 
-	refName := args[0]
-	if refName == "" {
+	if args[0] == "" {
 		qlog.Fatal("refName is empty, shouldn't use")
 	}
-	oldCommitId := args[1]
-	newCommitId := args[2]
 
-	update(refName, oldCommitId, newCommitId)
+	//updateEnv(args[0], args[1], args[2])
+
+	userName := os.Getenv("userName")
+	userId := os.Getenv("userId")
+	iUserId, _ := strconv.ParseInt(userId, 10, 64)
+	//repoId := os.Getenv("repoId")
+	repoName := os.Getenv("repoName")
+
+	models.Update(args[0], args[1], args[2], userName, repoName, iUserId)
 }