Browse Source

Completely rule out the cgo

Unknown 11 years ago
parent
commit
757e4f658c
6 changed files with 85 additions and 62 deletions
  1. 5 4
      .gopmfile
  2. 2 2
      README.md
  3. BIN
      conf/content/git-bare.zip
  4. 70 52
      models/repo.go
  5. 4 1
      models/user.go
  6. 4 3
      routers/repo/repo.go

+ 5 - 4
.gopmfile

@@ -4,17 +4,18 @@ path=github.com/gogits/gogs
 [deps]
 github.com/codegangsta/cli=
 github.com/codegangsta/martini=
-github.com/gogits/binding=
 github.com/martini-contrib/render=
 github.com/martini-contrib/sessions=
 github.com/Unknwon/com=
+github.com/Unknwon/cae=
+github.com/Unknwon/goconfig=
 github.com/dchest/scrypt=
 github.com/go-sql-driver/mysql=
-github.com/libgit2/git2go=commit:054268a63418b03892bfd4c6a509a0294660074b
 github.com/lunny/xorm=
-github.com/speedata/gogit=
-github.com/Unknwon/goconfig=
+github.com/slene/blackfriday=
 github.com/gogits/logs=
+github.com/gogits/binding=
+github.com/gogits/git=
 
 [res]
 include=templates|public|conf

+ 2 - 2
README.md

@@ -3,7 +3,7 @@ Gogs - Go Git Service [![wercker status](https://app.wercker.com/status/ad0bdb0b
 
 Gogs(Go Git Service) is a GitHub-like clone in the Go Programming Language.
 
-Since we choose to use pure Go implmentation of Git manipulation, Gogs certainly supports **ALL platforms**  that Go supports, including Linux, Max OS X, and Windows with **ZERO** dependency.
+Since we choose to use pure Go implementation of Git manipulation, Gogs certainly supports **ALL platforms**  that Go supports, including Linux, Max OS X, and Windows with **ZERO** dependency.
 
 ##### Current version: 0.0.9 Alpha
 
@@ -18,7 +18,7 @@ Please see [Wiki](https://github.com/gogits/gogs/wiki) for project design, devel
 ## Features
 
 - Activity timeline
-- SSH protocal support.
+- SSH protocol support.
 - Register/delete account.
 - Create/delete public repository.
 - User profile page.

BIN
conf/content/git-bare.zip


+ 70 - 52
models/repo.go

@@ -11,11 +11,14 @@ import (
 	"os"
 	"path/filepath"
 	"strings"
+	"sync"
 	"time"
 	"unicode/utf8"
 
+	"github.com/Unknwon/cae/zip"
 	"github.com/Unknwon/com"
-	git "github.com/libgit2/git2go"
+
+	"github.com/gogits/git"
 
 	"github.com/gogits/gogs/modules/base"
 	"github.com/gogits/gogs/modules/log"
@@ -44,6 +47,7 @@ type Star struct {
 }
 
 var (
+	gitInitLocker          = sync.Mutex{}
 	LanguageIgns, Licenses []string
 )
 
@@ -55,6 +59,8 @@ var (
 func init() {
 	LanguageIgns = strings.Split(base.Cfg.MustValue("repository", "LANG_IGNS"), "|")
 	Licenses = strings.Split(base.Cfg.MustValue("repository", "LICENSES"), "|")
+
+	zip.Verbose = false
 }
 
 // check if repository is exist
@@ -66,7 +72,7 @@ func IsRepositoryExist(user *User, repoName string) (bool, error) {
 	}
 	s, err := os.Stat(RepoPath(user.Name, repoName))
 	if err != nil {
-		return false, nil
+		return false, nil // Error simply means does not exist, but we don't want to show up.
 	}
 	return s.IsDir(), nil
 }
@@ -138,12 +144,59 @@ func CreateRepository(user *User, repoName, desc, repoLang, license string, priv
 	}
 
 	return repo, NewRepoAction(user, repo)
+	return nil, nil
+}
+
+// extractGitBareZip extracts git-bare.zip to repository path.
+func extractGitBareZip(repoPath string) error {
+	z, err := zip.Open("conf/content/git-bare.zip")
+	if err != nil {
+		fmt.Println("shi?")
+		return err
+	}
+	defer z.Close()
+
+	return z.ExtractTo(repoPath)
+}
+
+// initRepoCommit temporarily changes with work directory.
+func initRepoCommit(tmpPath string, sig *git.Signature) error {
+	gitInitLocker.Lock()
+	defer gitInitLocker.Unlock()
+
+	// Change work directory.
+	curPath, err := os.Getwd()
+	if err != nil {
+		return err
+	} else if err = os.Chdir(tmpPath); err != nil {
+		return err
+	}
+	defer os.Chdir(curPath)
+
+	if _, _, err := com.ExecCmd("git", "add", "--all"); err != nil {
+		return err
+	}
+	if _, _, err := com.ExecCmd("git", "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email),
+		"-m", "Init commit"); err != nil {
+		return err
+	}
+	if _, _, err := com.ExecCmd("git", "push", "origin", "master"); err != nil {
+		return err
+	}
+	return nil
 }
 
 // InitRepository initializes README and .gitignore if needed.
 func initRepository(f string, user *User, repo *Repository, initReadme bool, repoLang, license string) error {
-	fileName := map[string]string{}
+	repoPath := RepoPath(user.Name, repo.Name)
 
+	// Create bare new repository.
+	if err := extractGitBareZip(repoPath); err != nil {
+		return err
+	}
+
+	// Initialize repository according to user's choice.
+	fileName := map[string]string{}
 	if initReadme {
 		fileName["readme"] = "README.md"
 	}
@@ -154,87 +207,52 @@ func initRepository(f string, user *User, repo *Repository, initReadme bool, rep
 		fileName["license"] = "LICENSE"
 	}
 
-	workdir := filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond()))
-	os.MkdirAll(workdir, os.ModePerm)
+	// Clone to temprory path and do the init commit.
+	tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond()))
+	os.MkdirAll(tmpDir, os.ModePerm)
 
-	sig := user.NewGitSig()
+	if _, _, err := com.ExecCmd("git", "clone", repoPath, tmpDir); err != nil {
+		return err
+	}
 
 	// README
 	if initReadme {
 		defaultReadme := repo.Name + "\n" + strings.Repeat("=",
 			utf8.RuneCountInString(repo.Name)) + "\n\n" + repo.Description
-		if err := ioutil.WriteFile(filepath.Join(workdir, fileName["readme"]),
+		if err := ioutil.WriteFile(filepath.Join(tmpDir, fileName["readme"]),
 			[]byte(defaultReadme), 0644); err != nil {
 			return err
 		}
 	}
 
+	// .gitignore
 	if repoLang != "" {
-		// .gitignore
 		filePath := "conf/gitignore/" + repoLang
 		if com.IsFile(filePath) {
 			if _, err := com.Copy(filePath,
-				filepath.Join(workdir, fileName["gitign"])); err != nil {
+				filepath.Join(tmpDir, fileName["gitign"])); err != nil {
 				return err
 			}
 		}
 	}
 
+	// LICENSE
 	if license != "" {
-		// LICENSE
 		filePath := "conf/license/" + license
 		if com.IsFile(filePath) {
 			if _, err := com.Copy(filePath,
-				filepath.Join(workdir, fileName["license"])); err != nil {
+				filepath.Join(tmpDir, fileName["license"])); err != nil {
 				return err
 			}
 		}
 	}
 
-	rp, err := git.InitRepository(f, true)
-	if err != nil {
-		return err
-	}
-	rp.SetWorkdir(workdir, false)
-
-	idx, err := rp.Index()
-	if err != nil {
+	// Apply changes and commit.
+	if err := initRepoCommit(tmpDir, user.NewGitSig()); err != nil {
 		return err
 	}
 
-	for _, name := range fileName {
-		if err = idx.AddByPath(name); err != nil {
-			return err
-		}
-	}
-
-	treeId, err := idx.WriteTree()
-	if err != nil {
-		return err
-	}
-
-	message := "Init commit"
-	tree, err := rp.LookupTree(treeId)
-	if err != nil {
-		return err
-	}
-
-	if _, err = rp.CreateCommit("HEAD", sig, sig, message, tree); err != nil {
-		return err
-	}
-
-	pu, err := os.OpenFile(filepath.Join(f, "hooks", "post-update"), os.O_CREATE|os.O_WRONLY, 0777)
-	if err != nil {
-		return err
-	}
-	defer pu.Close()
-	ep, err := exePath()
-	if err != nil {
-		return err
-	}
-	_, err = pu.WriteString(fmt.Sprintf("#!/usr/bin/env bash\n%s update\n", ep))
-
-	return err
+	return nil
 }
 
 func GetRepositoryByName(user *User, repoName string) (*Repository, error) {

+ 4 - 1
models/user.go

@@ -13,8 +13,10 @@ import (
 	"time"
 
 	"github.com/dchest/scrypt"
+
+	"github.com/gogits/git"
+
 	"github.com/gogits/gogs/modules/base"
-	git "github.com/libgit2/git2go"
 )
 
 var UserPasswdSalt string
@@ -89,6 +91,7 @@ func IsEmailUsed(email string) (bool, error) {
 	return orm.Get(&User{Email: email})
 }
 
+// NewGitSig generates and returns the signature of given user.
 func (user *User) NewGitSig() *git.Signature {
 	return &git.Signature{
 		Name:  user.Name,

+ 4 - 3
routers/repo/repo.go

@@ -20,15 +20,16 @@ func Create(ctx *middleware.Context, form auth.CreateRepoForm) {
 		return
 	}
 
-	if _, err := models.CreateRepository(ctx.User,
-		form.RepoName, form.Description, form.Language, form.License,
-		form.Visibility == "private", form.InitReadme == "on"); err == nil {
+	_, err := models.CreateRepository(ctx.User, form.RepoName, form.Description,
+		form.Language, form.License, form.Visibility == "private", form.InitReadme == "on")
+	if err == nil {
 		ctx.Render.Redirect("/"+ctx.User.Name+"/"+form.RepoName, 302)
 		return
 	} else if err == models.ErrRepoAlreadyExist {
 		ctx.RenderWithErr("Repository name has already been used", "repo/create", &form)
 		return
 	}
+	ctx.Handle(200, "repo.Create", err)
 }
 
 func SettingPost(ctx *middleware.Context) {