mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	move out git module and #1573 send push hook
This commit is contained in:
		@@ -20,6 +20,7 @@ github.com/gogits/chardet = commit:2404f77725
 | 
				
			|||||||
github.com/gogits/git-shell = 
 | 
					github.com/gogits/git-shell = 
 | 
				
			||||||
github.com/gogits/go-gogs-client = commit:4b541fa
 | 
					github.com/gogits/go-gogs-client = commit:4b541fa
 | 
				
			||||||
github.com/issue9/identicon = commit:f8c0d2c
 | 
					github.com/issue9/identicon = commit:f8c0d2c
 | 
				
			||||||
 | 
					github.com/kardianos/minwinsvc = 
 | 
				
			||||||
github.com/klauspost/compress = commit:bcd0709
 | 
					github.com/klauspost/compress = commit:bcd0709
 | 
				
			||||||
github.com/klauspost/cpuid = commit:8d9fe96
 | 
					github.com/klauspost/cpuid = commit:8d9fe96
 | 
				
			||||||
github.com/klauspost/crc32 = commit:0aff1ea
 | 
					github.com/klauspost/crc32 = commit:0aff1ea
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@ Gogs - Go Git Service [
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##### Current version: 0.7.36 Beta
 | 
					##### Current version: 0.7.37 Beta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| Web | UI  | Preview  |
 | 
					| Web | UI  | Preview  |
 | 
				
			||||||
|:-------------:|:-------:|:-------:|
 | 
					|:-------------:|:-------:|:-------:|
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,8 @@ import (
 | 
				
			|||||||
	"gopkg.in/ini.v1"
 | 
						"gopkg.in/ini.v1"
 | 
				
			||||||
	"gopkg.in/macaron.v1"
 | 
						"gopkg.in/macaron.v1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/git-shell"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/models"
 | 
						"github.com/gogits/gogs/models"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/auth"
 | 
						"github.com/gogits/gogs/modules/auth"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/avatar"
 | 
						"github.com/gogits/gogs/modules/avatar"
 | 
				
			||||||
@@ -78,7 +80,6 @@ func checkVersion() {
 | 
				
			|||||||
	// Check dependency version.
 | 
						// Check dependency version.
 | 
				
			||||||
	checkers := []VerChecker{
 | 
						checkers := []VerChecker{
 | 
				
			||||||
		{"github.com/go-xorm/xorm", func() string { return xorm.Version }, "0.4.4.1029"},
 | 
							{"github.com/go-xorm/xorm", func() string { return xorm.Version }, "0.4.4.1029"},
 | 
				
			||||||
		{"github.com/Unknwon/macaron", macaron.Version, "0.5.4"},
 | 
					 | 
				
			||||||
		{"github.com/go-macaron/binding", binding.Version, "0.1.0"},
 | 
							{"github.com/go-macaron/binding", binding.Version, "0.1.0"},
 | 
				
			||||||
		{"github.com/go-macaron/cache", cache.Version, "0.1.2"},
 | 
							{"github.com/go-macaron/cache", cache.Version, "0.1.2"},
 | 
				
			||||||
		{"github.com/go-macaron/csrf", csrf.Version, "0.0.3"},
 | 
							{"github.com/go-macaron/csrf", csrf.Version, "0.0.3"},
 | 
				
			||||||
@@ -86,6 +87,8 @@ func checkVersion() {
 | 
				
			|||||||
		{"github.com/go-macaron/session", session.Version, "0.1.6"},
 | 
							{"github.com/go-macaron/session", session.Version, "0.1.6"},
 | 
				
			||||||
		{"github.com/go-macaron/toolbox", toolbox.Version, "0.1.0"},
 | 
							{"github.com/go-macaron/toolbox", toolbox.Version, "0.1.0"},
 | 
				
			||||||
		{"gopkg.in/ini.v1", ini.Version, "1.8.1"},
 | 
							{"gopkg.in/ini.v1", ini.Version, "1.8.1"},
 | 
				
			||||||
 | 
							{"gopkg.in/macaron.v1", macaron.Version, "0.8.0"},
 | 
				
			||||||
 | 
							{"github.com/gogits/git-shell", git.Version, "0.1.0"},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for _, c := range checkers {
 | 
						for _, c := range checkers {
 | 
				
			||||||
		if !version.Compare(c.Version(), c.Expected, ">=") {
 | 
							if !version.Compare(c.Version(), c.Expected, ">=") {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							@@ -18,7 +18,7 @@ import (
 | 
				
			|||||||
	"github.com/gogits/gogs/modules/setting"
 | 
						"github.com/gogits/gogs/modules/setting"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const APP_VER = "0.7.36.1209 Beta"
 | 
					const APP_VER = "0.7.37.1209 Beta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	runtime.GOMAXPROCS(runtime.NumCPU())
 | 
						runtime.GOMAXPROCS(runtime.NumCPU())
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,10 +17,10 @@ import (
 | 
				
			|||||||
	"github.com/Unknwon/com"
 | 
						"github.com/Unknwon/com"
 | 
				
			||||||
	"github.com/go-xorm/xorm"
 | 
						"github.com/go-xorm/xorm"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/git-shell"
 | 
				
			||||||
	api "github.com/gogits/go-gogs-client"
 | 
						api "github.com/gogits/go-gogs-client"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/modules/base"
 | 
						"github.com/gogits/gogs/modules/base"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/git"
 | 
					 | 
				
			||||||
	"github.com/gogits/gogs/modules/log"
 | 
						"github.com/gogits/gogs/modules/log"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/setting"
 | 
						"github.com/gogits/gogs/modules/setting"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -229,6 +229,28 @@ func NewPushCommits() *PushCommits {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (pc *PushCommits) ToApiPayloadCommits(repoLink string) []*api.PayloadCommit {
 | 
				
			||||||
 | 
						commits := make([]*api.PayloadCommit, len(pc.Commits))
 | 
				
			||||||
 | 
						for i, cmt := range pc.Commits {
 | 
				
			||||||
 | 
							author_username := ""
 | 
				
			||||||
 | 
							author, err := GetUserByEmail(cmt.AuthorEmail)
 | 
				
			||||||
 | 
							if err == nil {
 | 
				
			||||||
 | 
								author_username = author.Name
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							commits[i] = &api.PayloadCommit{
 | 
				
			||||||
 | 
								ID:      cmt.Sha1,
 | 
				
			||||||
 | 
								Message: cmt.Message,
 | 
				
			||||||
 | 
								URL:     fmt.Sprintf("%s/commit/%s", repoLink, cmt.Sha1),
 | 
				
			||||||
 | 
								Author: &api.PayloadAuthor{
 | 
				
			||||||
 | 
									Name:     cmt.AuthorName,
 | 
				
			||||||
 | 
									Email:    cmt.AuthorEmail,
 | 
				
			||||||
 | 
									UserName: author_username,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return commits
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AvatarLink tries to match user in database with e-mail
 | 
					// AvatarLink tries to match user in database with e-mail
 | 
				
			||||||
// in order to show custom avatar, and falls back to general avatar link.
 | 
					// in order to show custom avatar, and falls back to general avatar link.
 | 
				
			||||||
func (push *PushCommits) AvatarLink(email string) string {
 | 
					func (push *PushCommits) AvatarLink(email string) string {
 | 
				
			||||||
@@ -413,7 +435,7 @@ func CommitRepoAction(
 | 
				
			|||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		// if not the first commit, set the compareUrl
 | 
							// if not the first commit, set the compareUrl
 | 
				
			||||||
		if !strings.HasPrefix(oldCommitID, "0000000") {
 | 
							if !strings.HasPrefix(oldCommitID, "0000000") {
 | 
				
			||||||
			commit.CompareUrl = fmt.Sprintf("%s/%s/compare/%s...%s", repoUserName, repoName, oldCommitID, newCommitID)
 | 
								commit.CompareUrl = repo.ComposeCompareURL(oldCommitID, newCommitID)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			isNewBranch = true
 | 
								isNewBranch = true
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -469,30 +491,12 @@ func CommitRepoAction(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	switch opType {
 | 
						switch opType {
 | 
				
			||||||
	case COMMIT_REPO: // Push
 | 
						case COMMIT_REPO: // Push
 | 
				
			||||||
		commits := make([]*api.PayloadCommit, len(commit.Commits))
 | 
					 | 
				
			||||||
		for i, cmt := range commit.Commits {
 | 
					 | 
				
			||||||
			author_username := ""
 | 
					 | 
				
			||||||
			author, err := GetUserByEmail(cmt.AuthorEmail)
 | 
					 | 
				
			||||||
			if err == nil {
 | 
					 | 
				
			||||||
				author_username = author.Name
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			commits[i] = &api.PayloadCommit{
 | 
					 | 
				
			||||||
				ID:      cmt.Sha1,
 | 
					 | 
				
			||||||
				Message: cmt.Message,
 | 
					 | 
				
			||||||
				URL:     fmt.Sprintf("%s/commit/%s", repo.FullRepoLink(), cmt.Sha1),
 | 
					 | 
				
			||||||
				Author: &api.PayloadAuthor{
 | 
					 | 
				
			||||||
					Name:     cmt.AuthorName,
 | 
					 | 
				
			||||||
					Email:    cmt.AuthorEmail,
 | 
					 | 
				
			||||||
					UserName: author_username,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		p := &api.PushPayload{
 | 
							p := &api.PushPayload{
 | 
				
			||||||
			Ref:        refFullName,
 | 
								Ref:        refFullName,
 | 
				
			||||||
			Before:     oldCommitID,
 | 
								Before:     oldCommitID,
 | 
				
			||||||
			After:      newCommitID,
 | 
								After:      newCommitID,
 | 
				
			||||||
			CompareUrl: setting.AppUrl + commit.CompareUrl,
 | 
								CompareUrl: setting.AppUrl + commit.CompareUrl,
 | 
				
			||||||
			Commits:    commits,
 | 
								Commits:    commit.ToApiPayloadCommits(repo.FullRepoLink()),
 | 
				
			||||||
			Repo:       payloadRepo,
 | 
								Repo:       payloadRepo,
 | 
				
			||||||
			Pusher: &api.PayloadAuthor{
 | 
								Pusher: &api.PayloadAuthor{
 | 
				
			||||||
				Name:     pusher_name,
 | 
									Name:     pusher_name,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,9 @@ import (
 | 
				
			|||||||
	"github.com/Unknwon/com"
 | 
						"github.com/Unknwon/com"
 | 
				
			||||||
	"github.com/go-xorm/xorm"
 | 
						"github.com/go-xorm/xorm"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/modules/git"
 | 
						"github.com/gogits/git-shell"
 | 
				
			||||||
 | 
						api "github.com/gogits/go-gogs-client"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/modules/log"
 | 
						"github.com/gogits/gogs/modules/log"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/process"
 | 
						"github.com/gogits/gogs/modules/process"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/setting"
 | 
						"github.com/gogits/gogs/modules/setting"
 | 
				
			||||||
@@ -124,6 +126,12 @@ func (pr *PullRequest) CanAutoMerge() bool {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Merge merges pull request to base repository.
 | 
					// Merge merges pull request to base repository.
 | 
				
			||||||
func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error) {
 | 
					func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error) {
 | 
				
			||||||
 | 
						if err = pr.GetHeadRepo(); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("GetHeadRepo: %v", err)
 | 
				
			||||||
 | 
						} else if err = pr.GetBaseRepo(); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("GetBaseRepo: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sess := x.NewSession()
 | 
						sess := x.NewSession()
 | 
				
			||||||
	defer sessionRelease(sess)
 | 
						defer sessionRelease(sess)
 | 
				
			||||||
	if err = sess.Begin(); err != nil {
 | 
						if err = sess.Begin(); err != nil {
 | 
				
			||||||
@@ -134,18 +142,14 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
 | 
				
			|||||||
		return fmt.Errorf("Issue.changeStatus: %v", err)
 | 
							return fmt.Errorf("Issue.changeStatus: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err = pr.getHeadRepo(sess); err != nil {
 | 
					 | 
				
			||||||
		return fmt.Errorf("getHeadRepo: %v", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	headRepoPath := RepoPath(pr.HeadUserName, pr.HeadRepo.Name)
 | 
						headRepoPath := RepoPath(pr.HeadUserName, pr.HeadRepo.Name)
 | 
				
			||||||
	headGitRepo, err := git.OpenRepository(headRepoPath)
 | 
						headGitRepo, err := git.OpenRepository(headRepoPath)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return fmt.Errorf("OpenRepository: %v", err)
 | 
							return fmt.Errorf("OpenRepository: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	pr.MergedCommitID, err = headGitRepo.GetCommitIdOfBranch(pr.HeadBranch)
 | 
						pr.MergedCommitID, err = headGitRepo.GetBranchCommitID(pr.HeadBranch)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return fmt.Errorf("GetCommitIdOfBranch: %v", err)
 | 
							return fmt.Errorf("GetBranchCommitID: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err = mergePullRequestAction(sess, doer, pr.Issue.Repo, pr.Issue); err != nil {
 | 
						if err = mergePullRequestAction(sess, doer, pr.Issue.Repo, pr.Issue); err != nil {
 | 
				
			||||||
@@ -213,7 +217,38 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
 | 
				
			|||||||
		return fmt.Errorf("git push: %s", stderr)
 | 
							return fmt.Errorf("git push: %s", stderr)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return sess.Commit()
 | 
						if err = sess.Commit(); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("Commit: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Compose commit repository action
 | 
				
			||||||
 | 
						l, err := headGitRepo.CommitsBetweenIDs(pr.MergedCommitID, pr.MergeBase)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("CommitsBetween: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p := &api.PushPayload{
 | 
				
			||||||
 | 
							Ref:        "refs/heads/" + pr.BaseBranch,
 | 
				
			||||||
 | 
							Before:     pr.MergeBase,
 | 
				
			||||||
 | 
							After:      pr.MergedCommitID,
 | 
				
			||||||
 | 
							CompareUrl: setting.AppUrl + pr.BaseRepo.ComposeCompareURL(pr.MergeBase, pr.MergedCommitID),
 | 
				
			||||||
 | 
							Commits:    ListToPushCommits(l).ToApiPayloadCommits(pr.BaseRepo.FullRepoLink()),
 | 
				
			||||||
 | 
							Repo:       pr.BaseRepo.ComposePayload(),
 | 
				
			||||||
 | 
							Pusher: &api.PayloadAuthor{
 | 
				
			||||||
 | 
								Name:     pr.HeadRepo.MustOwner().DisplayName(),
 | 
				
			||||||
 | 
								Email:    pr.HeadRepo.MustOwner().Email,
 | 
				
			||||||
 | 
								UserName: pr.HeadRepo.MustOwner().Name,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Sender: &api.PayloadUser{
 | 
				
			||||||
 | 
								UserName:  doer.Name,
 | 
				
			||||||
 | 
								ID:        doer.Id,
 | 
				
			||||||
 | 
								AvatarUrl: setting.AppUrl + doer.RelAvatarLink(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err = PrepareWebhooks(pr.BaseRepo, HOOK_EVENT_PUSH, p); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("PrepareWebhooks: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						go HookQueue.Add(pr.BaseRepo.ID)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// patchConflicts is a list of conflit description from Git.
 | 
					// patchConflicts is a list of conflit description from Git.
 | 
				
			||||||
@@ -411,8 +446,6 @@ func (pr *PullRequest) UpdatePatch() (err error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if err = pr.GetBaseRepo(); err != nil {
 | 
						if err = pr.GetBaseRepo(); err != nil {
 | 
				
			||||||
		return fmt.Errorf("GetBaseRepo: %v", err)
 | 
							return fmt.Errorf("GetBaseRepo: %v", err)
 | 
				
			||||||
	} else if err = pr.BaseRepo.GetOwner(); err != nil {
 | 
					 | 
				
			||||||
		return fmt.Errorf("GetOwner: %v", err)
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())
 | 
						headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())
 | 
				
			||||||
@@ -422,7 +455,7 @@ func (pr *PullRequest) UpdatePatch() (err error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Add a temporary remote.
 | 
						// Add a temporary remote.
 | 
				
			||||||
	tmpRemote := com.ToStr(time.Now().UnixNano())
 | 
						tmpRemote := com.ToStr(time.Now().UnixNano())
 | 
				
			||||||
	if err = headGitRepo.AddRemote(tmpRemote, RepoPath(pr.BaseRepo.Owner.Name, pr.BaseRepo.Name)); err != nil {
 | 
						if err = headGitRepo.AddRemote(tmpRemote, RepoPath(pr.BaseRepo.MustOwner().Name, pr.BaseRepo.Name), true); err != nil {
 | 
				
			||||||
		return fmt.Errorf("AddRemote: %v", err)
 | 
							return fmt.Errorf("AddRemote: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer func() {
 | 
						defer func() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,8 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/go-xorm/xorm"
 | 
						"github.com/go-xorm/xorm"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/modules/git"
 | 
						"github.com/gogits/git-shell"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/modules/process"
 | 
						"github.com/gogits/gogs/modules/process"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -27,8 +28,8 @@ type Release struct {
 | 
				
			|||||||
	Target           string
 | 
						Target           string
 | 
				
			||||||
	Title            string
 | 
						Title            string
 | 
				
			||||||
	Sha1             string `xorm:"VARCHAR(40)"`
 | 
						Sha1             string `xorm:"VARCHAR(40)"`
 | 
				
			||||||
	NumCommits       int
 | 
						NumCommits       int64
 | 
				
			||||||
	NumCommitsBehind int    `xorm:"-"`
 | 
						NumCommitsBehind int64  `xorm:"-"`
 | 
				
			||||||
	Note             string `xorm:"TEXT"`
 | 
						Note             string `xorm:"TEXT"`
 | 
				
			||||||
	IsDraft          bool   `xorm:"NOT NULL DEFAULT false"`
 | 
						IsDraft          bool   `xorm:"NOT NULL DEFAULT false"`
 | 
				
			||||||
	IsPrerelease     bool
 | 
						IsPrerelease     bool
 | 
				
			||||||
@@ -51,31 +52,27 @@ func IsReleaseExist(repoID int64, tagName string) (bool, error) {
 | 
				
			|||||||
	return x.Get(&Release{RepoID: repoID, LowerTagName: strings.ToLower(tagName)})
 | 
						return x.Get(&Release{RepoID: repoID, LowerTagName: strings.ToLower(tagName)})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					 | 
				
			||||||
	git.GetVersion()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func createTag(gitRepo *git.Repository, rel *Release) error {
 | 
					func createTag(gitRepo *git.Repository, rel *Release) error {
 | 
				
			||||||
	// Only actual create when publish.
 | 
						// Only actual create when publish.
 | 
				
			||||||
	if !rel.IsDraft {
 | 
						if !rel.IsDraft {
 | 
				
			||||||
		if !gitRepo.IsTagExist(rel.TagName) {
 | 
							if !gitRepo.IsTagExist(rel.TagName) {
 | 
				
			||||||
			commit, err := gitRepo.GetCommitOfBranch(rel.Target)
 | 
								commit, err := gitRepo.GetBranchCommit(rel.Target)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return err
 | 
									return fmt.Errorf("GetBranchCommit: %v", err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil {
 | 
								if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil {
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			commit, err := gitRepo.GetCommitOfTag(rel.TagName)
 | 
								commit, err := gitRepo.GetTagCommit(rel.TagName)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return err
 | 
									return fmt.Errorf("GetTagCommit: %v", err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			rel.NumCommits, err = commit.CommitsCount()
 | 
								rel.NumCommits, err = commit.CommitsCount()
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return err
 | 
									return fmt.Errorf("CommitsCount: %v", err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -98,7 +98,7 @@ func NewRepoContext() {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Check Git version.
 | 
						// Check Git version.
 | 
				
			||||||
	gitVer, err := git.Version()
 | 
						gitVer, err := git.BinVersion()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Fatal(4, "Fail to get Git version: %v", err)
 | 
							log.Fatal(4, "Fail to get Git version: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -309,6 +309,10 @@ func (repo *Repository) RepoLink() string {
 | 
				
			|||||||
	return setting.AppSubUrl + "/" + repo.MustOwner().Name + "/" + repo.Name
 | 
						return setting.AppSubUrl + "/" + repo.MustOwner().Name + "/" + repo.Name
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (repo *Repository) ComposeCompareURL(oldCommitID, newCommitID string) string {
 | 
				
			||||||
 | 
						return fmt.Sprintf("%s/%s/compare/%s...%s", repo.MustOwner().Name, repo.Name, oldCommitID, newCommitID)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (repo *Repository) FullRepoLink() string {
 | 
					func (repo *Repository) FullRepoLink() string {
 | 
				
			||||||
	return setting.AppUrl + repo.MustOwner().Name + "/" + repo.Name
 | 
						return setting.AppUrl + repo.MustOwner().Name + "/" + repo.Name
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,8 @@ import (
 | 
				
			|||||||
	"os/exec"
 | 
						"os/exec"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/modules/git"
 | 
						"github.com/gogits/git-shell"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/modules/log"
 | 
						"github.com/gogits/gogs/modules/log"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -46,6 +47,24 @@ func DeleteUpdateTaskByUUID(uuid string) error {
 | 
				
			|||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName string, userID int64) error {
 | 
					func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName string, userID int64) error {
 | 
				
			||||||
	isNew := strings.HasPrefix(oldCommitID, "0000000")
 | 
						isNew := strings.HasPrefix(oldCommitID, "0000000")
 | 
				
			||||||
	if isNew &&
 | 
						if isNew &&
 | 
				
			||||||
@@ -131,24 +150,8 @@ func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName
 | 
				
			|||||||
		return fmt.Errorf("runUpdate.Commit repoId: %v", err)
 | 
							return fmt.Errorf("runUpdate.Commit repoId: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Push commits.
 | 
						if err = CommitRepoAction(userID, user.Id, userName, user.Email,
 | 
				
			||||||
	commits := make([]*PushCommit, 0)
 | 
							repo.ID, repoUserName, repoName, refName, ListToPushCommits(l), oldCommitID, newCommitID); err != nil {
 | 
				
			||||||
	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,
 | 
					 | 
				
			||||||
			})
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err = CommitRepoAction(userID, user.Id, userName, actEmail,
 | 
					 | 
				
			||||||
		repo.ID, repoUserName, repoName, refName, &PushCommits{l.Len(), commits, "", nil}, oldCommitID, newCommitID); err != nil {
 | 
					 | 
				
			||||||
		return fmt.Errorf("runUpdate.models.CommitRepoAction: %s/%s:%v", repoUserName, repoName, err)
 | 
							return fmt.Errorf("runUpdate.models.CommitRepoAction: %s/%s:%v", repoUserName, repoName, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,7 +29,6 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/modules/avatar"
 | 
						"github.com/gogits/gogs/modules/avatar"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/base"
 | 
						"github.com/gogits/gogs/modules/base"
 | 
				
			||||||
	oldgit "github.com/gogits/gogs/modules/git"
 | 
					 | 
				
			||||||
	"github.com/gogits/gogs/modules/log"
 | 
						"github.com/gogits/gogs/modules/log"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/setting"
 | 
						"github.com/gogits/gogs/modules/setting"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -940,11 +939,11 @@ func MakeEmailPrimary(email *EmailAddress) error {
 | 
				
			|||||||
// UserCommit represents a commit with validation of user.
 | 
					// UserCommit represents a commit with validation of user.
 | 
				
			||||||
type UserCommit struct {
 | 
					type UserCommit struct {
 | 
				
			||||||
	User *User
 | 
						User *User
 | 
				
			||||||
	*oldgit.Commit
 | 
						*git.Commit
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ValidateCommitWithEmail chceck if author's e-mail of commit is corresponsind to a user.
 | 
					// ValidateCommitWithEmail chceck if author's e-mail of commit is corresponsind to a user.
 | 
				
			||||||
func ValidateCommitWithEmail(c *oldgit.Commit) *User {
 | 
					func ValidateCommitWithEmail(c *git.Commit) *User {
 | 
				
			||||||
	u, err := GetUserByEmail(c.Author.Email)
 | 
						u, err := GetUserByEmail(c.Author.Email)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
@@ -961,7 +960,7 @@ func ValidateCommitsWithEmails(oldCommits *list.List) *list.List {
 | 
				
			|||||||
		e          = oldCommits.Front()
 | 
							e          = oldCommits.Front()
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	for e != nil {
 | 
						for e != nil {
 | 
				
			||||||
		c := e.Value.(*oldgit.Commit)
 | 
							c := e.Value.(*git.Commit)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if v, ok := emails[c.Author.Email]; !ok {
 | 
							if v, ok := emails[c.Author.Email]; !ok {
 | 
				
			||||||
			u, _ = GetUserByEmail(c.Author.Email)
 | 
								u, _ = GetUserByEmail(c.Author.Email)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,9 +10,8 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/git-shell"
 | 
				
			||||||
	api "github.com/gogits/go-gogs-client"
 | 
						api "github.com/gogits/go-gogs-client"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/gogits/gogs/modules/git"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type SlackMeta struct {
 | 
					type SlackMeta struct {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,26 +0,0 @@
 | 
				
			|||||||
// 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"io"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/Unknwon/com"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type Blob struct {
 | 
					 | 
				
			||||||
	repo *Repository
 | 
					 | 
				
			||||||
	*TreeEntry
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (b *Blob) Data() (io.Reader, error) {
 | 
					 | 
				
			||||||
	stdout, stderr, err := com.ExecCmdDirBytes(b.repo.Path, "git", "show", b.ID.String())
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, errors.New(string(stderr))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return bytes.NewBuffer(stdout), nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,162 +0,0 @@
 | 
				
			|||||||
// 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bufio"
 | 
					 | 
				
			||||||
	"container/list"
 | 
					 | 
				
			||||||
	"net/http"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Commit represents a git commit.
 | 
					 | 
				
			||||||
type Commit struct {
 | 
					 | 
				
			||||||
	Tree
 | 
					 | 
				
			||||||
	ID            sha1 // The id of this commit object
 | 
					 | 
				
			||||||
	Author        *Signature
 | 
					 | 
				
			||||||
	Committer     *Signature
 | 
					 | 
				
			||||||
	CommitMessage string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	parents    []sha1 // sha1 strings
 | 
					 | 
				
			||||||
	submodules map[string]*SubModule
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Return the commit message. Same as retrieving CommitMessage directly.
 | 
					 | 
				
			||||||
func (c *Commit) Message() string {
 | 
					 | 
				
			||||||
	return c.CommitMessage
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Commit) Summary() string {
 | 
					 | 
				
			||||||
	return strings.Split(c.CommitMessage, "\n")[0]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Return oid of the parent number n (0-based index). Return nil if no such parent exists.
 | 
					 | 
				
			||||||
func (c *Commit) ParentId(n int) (id sha1, err error) {
 | 
					 | 
				
			||||||
	if n >= len(c.parents) {
 | 
					 | 
				
			||||||
		err = IDNotExist
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return c.parents[n], nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Return parent number n (0-based index)
 | 
					 | 
				
			||||||
func (c *Commit) Parent(n int) (*Commit, error) {
 | 
					 | 
				
			||||||
	id, err := c.ParentId(n)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	parent, err := c.repo.getCommit(id)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return parent, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Return the number of parents of the commit. 0 if this is the
 | 
					 | 
				
			||||||
// root commit, otherwise 1,2,...
 | 
					 | 
				
			||||||
func (c *Commit) ParentCount() int {
 | 
					 | 
				
			||||||
	return len(c.parents)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Commit) CommitsBefore() (*list.List, error) {
 | 
					 | 
				
			||||||
	return c.repo.getCommitsBefore(c.ID)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Commit) CommitsBeforeUntil(commitId string) (*list.List, error) {
 | 
					 | 
				
			||||||
	ec, err := c.repo.GetCommit(commitId)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return c.repo.CommitsBetween(c, ec)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Commit) CommitsCount() (int, error) {
 | 
					 | 
				
			||||||
	return c.repo.commitsCount(c.ID)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Commit) SearchCommits(keyword string) (*list.List, error) {
 | 
					 | 
				
			||||||
	return c.repo.searchCommits(c.ID, keyword)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Commit) CommitsByRange(page int) (*list.List, error) {
 | 
					 | 
				
			||||||
	return c.repo.commitsByRange(c.ID, page)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Commit) GetCommitOfRelPath(relPath string) (*Commit, error) {
 | 
					 | 
				
			||||||
	return c.repo.getCommitOfRelPath(c.ID, relPath)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Commit) GetSubModule(entryname string) (*SubModule, error) {
 | 
					 | 
				
			||||||
	modules, err := c.GetSubModules()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return modules[entryname], nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Commit) GetSubModules() (map[string]*SubModule, error) {
 | 
					 | 
				
			||||||
	if c.submodules != nil {
 | 
					 | 
				
			||||||
		return c.submodules, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	entry, err := c.GetTreeEntryByPath(".gitmodules")
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	rd, err := entry.Blob().Data()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	scanner := bufio.NewScanner(rd)
 | 
					 | 
				
			||||||
	c.submodules = make(map[string]*SubModule)
 | 
					 | 
				
			||||||
	var ismodule bool
 | 
					 | 
				
			||||||
	var path string
 | 
					 | 
				
			||||||
	for scanner.Scan() {
 | 
					 | 
				
			||||||
		if strings.HasPrefix(scanner.Text(), "[submodule") {
 | 
					 | 
				
			||||||
			ismodule = true
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if ismodule {
 | 
					 | 
				
			||||||
			fields := strings.Split(scanner.Text(), "=")
 | 
					 | 
				
			||||||
			k := strings.TrimSpace(fields[0])
 | 
					 | 
				
			||||||
			if k == "path" {
 | 
					 | 
				
			||||||
				path = strings.TrimSpace(fields[1])
 | 
					 | 
				
			||||||
			} else if k == "url" {
 | 
					 | 
				
			||||||
				c.submodules[path] = &SubModule{path, strings.TrimSpace(fields[1])}
 | 
					 | 
				
			||||||
				ismodule = false
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return c.submodules, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func isImageFile(data []byte) (string, bool) {
 | 
					 | 
				
			||||||
	contentType := http.DetectContentType(data)
 | 
					 | 
				
			||||||
	if strings.Index(contentType, "image/") != -1 {
 | 
					 | 
				
			||||||
		return contentType, true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return contentType, false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Commit) IsImageFile(name string) bool {
 | 
					 | 
				
			||||||
	blob, err := c.GetBlobByPath(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dataRc, err := blob.Data()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	buf := make([]byte, 1024)
 | 
					 | 
				
			||||||
	n, _ := dataRc.Read(buf)
 | 
					 | 
				
			||||||
	if n > 0 {
 | 
					 | 
				
			||||||
		buf = buf[:n]
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	_, isImage := isImageFile(buf)
 | 
					 | 
				
			||||||
	return isImage
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,36 +0,0 @@
 | 
				
			|||||||
// 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/Unknwon/com"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type ArchiveType int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	ZIP ArchiveType = iota + 1
 | 
					 | 
				
			||||||
	TARGZ
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Commit) CreateArchive(path string, archiveType ArchiveType) error {
 | 
					 | 
				
			||||||
	var format string
 | 
					 | 
				
			||||||
	switch archiveType {
 | 
					 | 
				
			||||||
	case ZIP:
 | 
					 | 
				
			||||||
		format = "zip"
 | 
					 | 
				
			||||||
	case TARGZ:
 | 
					 | 
				
			||||||
		format = "tar.gz"
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return fmt.Errorf("unknown format: %v", archiveType)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_, stderr, err := com.ExecCmdDir(c.repo.Path, "git", "archive", "--format="+format, "-o", path, c.ID.String())
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return fmt.Errorf("%s", stderr)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,22 +0,0 @@
 | 
				
			|||||||
// Copyright 2015 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type ErrUnsupportedVersion struct {
 | 
					 | 
				
			||||||
	Required string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func IsErrUnsupportedVersion(err error) bool {
 | 
					 | 
				
			||||||
	_, ok := err.(ErrUnsupportedVersion)
 | 
					 | 
				
			||||||
	return ok
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (err ErrUnsupportedVersion) Error() string {
 | 
					 | 
				
			||||||
	return fmt.Sprintf("Operation requires higher version [required: %s]", err.Required)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,125 +0,0 @@
 | 
				
			|||||||
// 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"io/ioutil"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"path"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/Unknwon/com"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// hookNames is a list of Git hooks' name that are supported.
 | 
					 | 
				
			||||||
var hookNames = []string{
 | 
					 | 
				
			||||||
	"applypatch-msg",
 | 
					 | 
				
			||||||
	"pre-applypatch",
 | 
					 | 
				
			||||||
	"post-applypatch",
 | 
					 | 
				
			||||||
	"pre-commit",
 | 
					 | 
				
			||||||
	"prepare-commit-msg",
 | 
					 | 
				
			||||||
	"commit-msg",
 | 
					 | 
				
			||||||
	"post-commit",
 | 
					 | 
				
			||||||
	"pre-rebase",
 | 
					 | 
				
			||||||
	"post-checkout",
 | 
					 | 
				
			||||||
	"post-merge",
 | 
					 | 
				
			||||||
	"pre-push",
 | 
					 | 
				
			||||||
	"pre-receive",
 | 
					 | 
				
			||||||
	// "update",
 | 
					 | 
				
			||||||
	"post-receive",
 | 
					 | 
				
			||||||
	"post-update",
 | 
					 | 
				
			||||||
	"push-to-checkout",
 | 
					 | 
				
			||||||
	"pre-auto-gc",
 | 
					 | 
				
			||||||
	"post-rewrite",
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	ErrNotValidHook = errors.New("not a valid Git hook")
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// IsValidHookName returns true if given name is a valid Git hook.
 | 
					 | 
				
			||||||
func IsValidHookName(name string) bool {
 | 
					 | 
				
			||||||
	for _, hn := range hookNames {
 | 
					 | 
				
			||||||
		if hn == name {
 | 
					 | 
				
			||||||
			return true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Hook represents a Git hook.
 | 
					 | 
				
			||||||
type Hook struct {
 | 
					 | 
				
			||||||
	name     string
 | 
					 | 
				
			||||||
	IsActive bool   // Indicates whether repository has this hook.
 | 
					 | 
				
			||||||
	Content  string // Content of hook if it's active.
 | 
					 | 
				
			||||||
	Sample   string // Sample content from Git.
 | 
					 | 
				
			||||||
	path     string // Hook file path.
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetHook returns a Git hook by given name and repository.
 | 
					 | 
				
			||||||
func GetHook(repoPath, name string) (*Hook, error) {
 | 
					 | 
				
			||||||
	if !IsValidHookName(name) {
 | 
					 | 
				
			||||||
		return nil, ErrNotValidHook
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	h := &Hook{
 | 
					 | 
				
			||||||
		name: name,
 | 
					 | 
				
			||||||
		path: path.Join(repoPath, "hooks", name),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if isFile(h.path) {
 | 
					 | 
				
			||||||
		data, err := ioutil.ReadFile(h.path)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		h.IsActive = true
 | 
					 | 
				
			||||||
		h.Content = string(data)
 | 
					 | 
				
			||||||
	} else if isFile(h.path + ".sample") {
 | 
					 | 
				
			||||||
		data, err := ioutil.ReadFile(h.path + ".sample")
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		h.Sample = string(data)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return h, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (h *Hook) Name() string {
 | 
					 | 
				
			||||||
	return h.name
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Update updates hook settings.
 | 
					 | 
				
			||||||
func (h *Hook) Update() error {
 | 
					 | 
				
			||||||
	if len(strings.TrimSpace(h.Content)) == 0 {
 | 
					 | 
				
			||||||
		if com.IsExist(h.path) {
 | 
					 | 
				
			||||||
			return os.Remove(h.path)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return ioutil.WriteFile(h.path, []byte(strings.Replace(h.Content, "\r", "", -1)), os.ModePerm)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ListHooks returns a list of Git hooks of given repository.
 | 
					 | 
				
			||||||
func ListHooks(repoPath string) (_ []*Hook, err error) {
 | 
					 | 
				
			||||||
	if !isDir(path.Join(repoPath, "hooks")) {
 | 
					 | 
				
			||||||
		return nil, errors.New("hooks path does not exist")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	hooks := make([]*Hook, len(hookNames))
 | 
					 | 
				
			||||||
	for i, name := range hookNames {
 | 
					 | 
				
			||||||
		hooks[i], err = GetHook(repoPath, name)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return hooks, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) GetHook(name string) (*Hook, error) {
 | 
					 | 
				
			||||||
	return GetHook(repo.Path, name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) Hooks() ([]*Hook, error) {
 | 
					 | 
				
			||||||
	return ListHooks(repo.Path)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,30 +0,0 @@
 | 
				
			|||||||
// 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Repository represents a Git repository.
 | 
					 | 
				
			||||||
type Repository struct {
 | 
					 | 
				
			||||||
	Path string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	commitCache map[sha1]*Commit
 | 
					 | 
				
			||||||
	tagCache    map[sha1]*Tag
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// OpenRepository opens the repository at the given path.
 | 
					 | 
				
			||||||
func OpenRepository(repoPath string) (*Repository, error) {
 | 
					 | 
				
			||||||
	repoPath, err := filepath.Abs(repoPath)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	} else if !isDir(repoPath) {
 | 
					 | 
				
			||||||
		return nil, errors.New("no such file or directory")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return &Repository{Path: repoPath}, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,50 +0,0 @@
 | 
				
			|||||||
// 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/Unknwon/com"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func IsBranchExist(repoPath, branchName string) bool {
 | 
					 | 
				
			||||||
	_, _, err := com.ExecCmdDir(repoPath, "git", "show-ref", "--verify", "refs/heads/"+branchName)
 | 
					 | 
				
			||||||
	return err == nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) IsBranchExist(branchName string) bool {
 | 
					 | 
				
			||||||
	return IsBranchExist(repo.Path, branchName)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) GetBranches() ([]string, error) {
 | 
					 | 
				
			||||||
	stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "show-ref", "--heads")
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, concatenateError(err, stderr)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	infos := strings.Split(stdout, "\n")
 | 
					 | 
				
			||||||
	branches := make([]string, len(infos)-1)
 | 
					 | 
				
			||||||
	for i, info := range infos[:len(infos)-1] {
 | 
					 | 
				
			||||||
		parts := strings.Split(info, " ")
 | 
					 | 
				
			||||||
		if len(parts) != 2 {
 | 
					 | 
				
			||||||
			continue // NOTE: I should believe git will not give me wrong string.
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		branches[i] = strings.TrimPrefix(parts[1], "refs/heads/")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return branches, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SetDefaultBranch sets default branch of repository.
 | 
					 | 
				
			||||||
func (repo *Repository) SetDefaultBranch(branchName string) error {
 | 
					 | 
				
			||||||
	if gitVer.LessThan(MustParseVersion("1.7.10")) {
 | 
					 | 
				
			||||||
		return ErrUnsupportedVersion{"1.7.10"}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_, stderr, err := com.ExecCmdDir(repo.Path, "git", "symbolic-ref", "HEAD", "refs/heads/"+branchName)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return concatenateError(err, stderr)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,341 +0,0 @@
 | 
				
			|||||||
// 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"container/list"
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"sync"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/Unknwon/com"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) getCommitIdOfRef(refpath string) (string, error) {
 | 
					 | 
				
			||||||
	stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "show-ref", "--verify", refpath)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return "", errors.New(stderr)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return strings.Split(stdout, " ")[0], nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) GetCommitIdOfBranch(branchName string) (string, error) {
 | 
					 | 
				
			||||||
	return repo.getCommitIdOfRef("refs/heads/" + branchName)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// get branch's last commit or a special commit by id string
 | 
					 | 
				
			||||||
func (repo *Repository) GetCommitOfBranch(branchName string) (*Commit, error) {
 | 
					 | 
				
			||||||
	commitId, err := repo.GetCommitIdOfBranch(branchName)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return repo.GetCommit(commitId)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) GetCommitIdOfTag(tagName string) (string, error) {
 | 
					 | 
				
			||||||
	return repo.getCommitIdOfRef("refs/tags/" + tagName)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) GetCommitOfTag(tagName string) (*Commit, error) {
 | 
					 | 
				
			||||||
	tag, err := repo.GetTag(tagName)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return tag.Commit()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Parse commit information from the (uncompressed) raw
 | 
					 | 
				
			||||||
// data from the commit object.
 | 
					 | 
				
			||||||
// \n\n separate headers from message
 | 
					 | 
				
			||||||
func parseCommitData(data []byte) (*Commit, error) {
 | 
					 | 
				
			||||||
	commit := new(Commit)
 | 
					 | 
				
			||||||
	commit.parents = make([]sha1, 0, 1)
 | 
					 | 
				
			||||||
	// we now have the contents of the commit object. Let's investigate...
 | 
					 | 
				
			||||||
	nextline := 0
 | 
					 | 
				
			||||||
l:
 | 
					 | 
				
			||||||
	for {
 | 
					 | 
				
			||||||
		eol := bytes.IndexByte(data[nextline:], '\n')
 | 
					 | 
				
			||||||
		switch {
 | 
					 | 
				
			||||||
		case eol > 0:
 | 
					 | 
				
			||||||
			line := data[nextline : nextline+eol]
 | 
					 | 
				
			||||||
			spacepos := bytes.IndexByte(line, ' ')
 | 
					 | 
				
			||||||
			reftype := line[:spacepos]
 | 
					 | 
				
			||||||
			switch string(reftype) {
 | 
					 | 
				
			||||||
			case "tree":
 | 
					 | 
				
			||||||
				id, err := NewIdFromString(string(line[spacepos+1:]))
 | 
					 | 
				
			||||||
				if err != nil {
 | 
					 | 
				
			||||||
					return nil, err
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				commit.Tree.ID = id
 | 
					 | 
				
			||||||
			case "parent":
 | 
					 | 
				
			||||||
				// A commit can have one or more parents
 | 
					 | 
				
			||||||
				oid, err := NewIdFromString(string(line[spacepos+1:]))
 | 
					 | 
				
			||||||
				if err != nil {
 | 
					 | 
				
			||||||
					return nil, err
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				commit.parents = append(commit.parents, oid)
 | 
					 | 
				
			||||||
			case "author":
 | 
					 | 
				
			||||||
				sig, err := newSignatureFromCommitline(line[spacepos+1:])
 | 
					 | 
				
			||||||
				if err != nil {
 | 
					 | 
				
			||||||
					return nil, err
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				commit.Author = sig
 | 
					 | 
				
			||||||
			case "committer":
 | 
					 | 
				
			||||||
				sig, err := newSignatureFromCommitline(line[spacepos+1:])
 | 
					 | 
				
			||||||
				if err != nil {
 | 
					 | 
				
			||||||
					return nil, err
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				commit.Committer = sig
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			nextline += eol + 1
 | 
					 | 
				
			||||||
		case eol == 0:
 | 
					 | 
				
			||||||
			commit.CommitMessage = string(data[nextline+1:])
 | 
					 | 
				
			||||||
			break l
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			break l
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return commit, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) getCommit(id sha1) (*Commit, error) {
 | 
					 | 
				
			||||||
	if repo.commitCache != nil {
 | 
					 | 
				
			||||||
		if c, ok := repo.commitCache[id]; ok {
 | 
					 | 
				
			||||||
			return c, nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		repo.commitCache = make(map[sha1]*Commit, 10)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	data, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "cat-file", "-p", id.String())
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, concatenateError(err, string(stderr))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	commit, err := parseCommitData(data)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	commit.repo = repo
 | 
					 | 
				
			||||||
	commit.ID = id
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	repo.commitCache[id] = commit
 | 
					 | 
				
			||||||
	return commit, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Find the commit object in the repository.
 | 
					 | 
				
			||||||
func (repo *Repository) GetCommit(commitId string) (*Commit, error) {
 | 
					 | 
				
			||||||
	id, err := NewIdFromString(commitId)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return repo.getCommit(id)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) commitsCount(id sha1) (int, error) {
 | 
					 | 
				
			||||||
	if gitVer.LessThan(MustParseVersion("1.8.0")) {
 | 
					 | 
				
			||||||
		stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log",
 | 
					 | 
				
			||||||
			"--pretty=format:''", id.String())
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return 0, errors.New(string(stderr))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return len(bytes.Split(stdout, []byte("\n"))), nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "rev-list", "--count", id.String())
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return 0, errors.New(stderr)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return com.StrTo(strings.TrimSpace(stdout)).Int()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) CommitsCount(commitId string) (int, error) {
 | 
					 | 
				
			||||||
	id, err := NewIdFromString(commitId)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return 0, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return repo.commitsCount(id)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) commitsCountBetween(start, end sha1) (int, error) {
 | 
					 | 
				
			||||||
	if gitVer.LessThan(MustParseVersion("1.8.0")) {
 | 
					 | 
				
			||||||
		stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log",
 | 
					 | 
				
			||||||
			"--pretty=format:''", start.String()+"..."+end.String())
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return 0, errors.New(string(stderr))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return len(bytes.Split(stdout, []byte("\n"))), nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "rev-list", "--count",
 | 
					 | 
				
			||||||
		start.String()+"..."+end.String())
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return 0, errors.New(stderr)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return com.StrTo(strings.TrimSpace(stdout)).Int()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) CommitsCountBetween(startCommitID, endCommitID string) (int, error) {
 | 
					 | 
				
			||||||
	start, err := NewIdFromString(startCommitID)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return 0, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	end, err := NewIdFromString(endCommitID)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return 0, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return repo.commitsCountBetween(start, end)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) FilesCountBetween(startCommitID, endCommitID string) (int, error) {
 | 
					 | 
				
			||||||
	stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "diff", "--name-only",
 | 
					 | 
				
			||||||
		startCommitID+"..."+endCommitID)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return 0, fmt.Errorf("list changed files: %v", concatenateError(err, stderr))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return len(strings.Split(stdout, "\n")) - 1, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// used only for single tree, (]
 | 
					 | 
				
			||||||
func (repo *Repository) CommitsBetween(last *Commit, before *Commit) (*list.List, error) {
 | 
					 | 
				
			||||||
	l := list.New()
 | 
					 | 
				
			||||||
	if last == nil || last.ParentCount() == 0 {
 | 
					 | 
				
			||||||
		return l, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var err error
 | 
					 | 
				
			||||||
	cur := last
 | 
					 | 
				
			||||||
	for {
 | 
					 | 
				
			||||||
		if cur.ID.Equal(before.ID) {
 | 
					 | 
				
			||||||
			break
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		l.PushBack(cur)
 | 
					 | 
				
			||||||
		if cur.ParentCount() == 0 {
 | 
					 | 
				
			||||||
			break
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		cur, err = cur.Parent(0)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return l, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) commitsBefore(lock *sync.Mutex, l *list.List, parent *list.Element, id sha1, limit int) error {
 | 
					 | 
				
			||||||
	commit, err := repo.getCommit(id)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return fmt.Errorf("getCommit: %v", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var e *list.Element
 | 
					 | 
				
			||||||
	if parent == nil {
 | 
					 | 
				
			||||||
		e = l.PushBack(commit)
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		var in = parent
 | 
					 | 
				
			||||||
		for {
 | 
					 | 
				
			||||||
			if in == nil {
 | 
					 | 
				
			||||||
				break
 | 
					 | 
				
			||||||
			} else if in.Value.(*Commit).ID.Equal(commit.ID) {
 | 
					 | 
				
			||||||
				return nil
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				if in.Next() == nil {
 | 
					 | 
				
			||||||
					break
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if in.Value.(*Commit).Committer.When.Equal(commit.Committer.When) {
 | 
					 | 
				
			||||||
					break
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if in.Value.(*Commit).Committer.When.After(commit.Committer.When) &&
 | 
					 | 
				
			||||||
					in.Next().Value.(*Commit).Committer.When.Before(commit.Committer.When) {
 | 
					 | 
				
			||||||
					break
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			in = in.Next()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		e = l.InsertAfter(commit, in)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var pr = parent
 | 
					 | 
				
			||||||
	if commit.ParentCount() > 1 {
 | 
					 | 
				
			||||||
		pr = e
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for i := 0; i < commit.ParentCount(); i++ {
 | 
					 | 
				
			||||||
		id, err := commit.ParentId(i)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		err = repo.commitsBefore(lock, l, pr, id, 0)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) FileCommitsCount(branch, file string) (int, error) {
 | 
					 | 
				
			||||||
	stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "rev-list", "--count",
 | 
					 | 
				
			||||||
		branch, "--", file)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return 0, errors.New(stderr)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return com.StrTo(strings.TrimSpace(stdout)).Int()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) CommitsByFileAndRange(branch, file string, page int) (*list.List, error) {
 | 
					 | 
				
			||||||
	stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log", branch,
 | 
					 | 
				
			||||||
		"--skip="+com.ToStr((page-1)*50), "--max-count=50", prettyLogFormat, "--", file)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, errors.New(string(stderr))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return parsePrettyFormatLog(repo, stdout)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) getCommitsBefore(id sha1) (*list.List, error) {
 | 
					 | 
				
			||||||
	l := list.New()
 | 
					 | 
				
			||||||
	lock := new(sync.Mutex)
 | 
					 | 
				
			||||||
	return l, repo.commitsBefore(lock, l, nil, id, 0)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) searchCommits(id sha1, keyword string) (*list.List, error) {
 | 
					 | 
				
			||||||
	stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log", id.String(), "-100",
 | 
					 | 
				
			||||||
		"-i", "--grep="+keyword, prettyLogFormat)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	} else if len(stderr) > 0 {
 | 
					 | 
				
			||||||
		return nil, errors.New(string(stderr))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return parsePrettyFormatLog(repo, stdout)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var CommitsRangeSize = 50
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) commitsByRange(id sha1, page int) (*list.List, error) {
 | 
					 | 
				
			||||||
	stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log", id.String(),
 | 
					 | 
				
			||||||
		"--skip="+com.ToStr((page-1)*CommitsRangeSize), "--max-count="+com.ToStr(CommitsRangeSize), prettyLogFormat)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, errors.New(string(stderr))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return parsePrettyFormatLog(repo, stdout)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) getCommitOfRelPath(id sha1, relPath string) (*Commit, error) {
 | 
					 | 
				
			||||||
	stdout, _, err := com.ExecCmdDir(repo.Path, "git", "log", "-1", prettyLogFormat, id.String(), "--", relPath)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	id, err = NewIdFromString(string(stdout))
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return repo.getCommit(id)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,14 +0,0 @@
 | 
				
			|||||||
// 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type ObjectType string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	COMMIT ObjectType = "commit"
 | 
					 | 
				
			||||||
	TREE   ObjectType = "tree"
 | 
					 | 
				
			||||||
	BLOB   ObjectType = "blob"
 | 
					 | 
				
			||||||
	TAG    ObjectType = "tag"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
@@ -1,104 +0,0 @@
 | 
				
			|||||||
// Copyright 2015 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"container/list"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/Unknwon/com"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type PullRequestInfo struct {
 | 
					 | 
				
			||||||
	MergeBase string
 | 
					 | 
				
			||||||
	Commits   *list.List
 | 
					 | 
				
			||||||
	// Diff      *Diff
 | 
					 | 
				
			||||||
	NumFiles int
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetMergeBase checks and returns merge base of two branches.
 | 
					 | 
				
			||||||
func (repo *Repository) GetMergeBase(remoteBranch, headBranch string) (string, error) {
 | 
					 | 
				
			||||||
	// Get merge base commit.
 | 
					 | 
				
			||||||
	stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "merge-base", remoteBranch, headBranch)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return "", fmt.Errorf("get merge base: %v", concatenateError(err, stderr))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return strings.TrimSpace(stdout), nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// AddRemote adds a remote to repository.
 | 
					 | 
				
			||||||
func (repo *Repository) AddRemote(name, path string) error {
 | 
					 | 
				
			||||||
	_, stderr, err := com.ExecCmdDir(repo.Path, "git", "remote", "add", "-f", name, path)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return fmt.Errorf("add remote(%s - %s): %v", name, path, concatenateError(err, stderr))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// RemoveRemote removes a remote from repository.
 | 
					 | 
				
			||||||
func (repo *Repository) RemoveRemote(name string) error {
 | 
					 | 
				
			||||||
	_, stderr, err := com.ExecCmdDir(repo.Path, "git", "remote", "remove", name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return fmt.Errorf("remove remote(%s): %v", name, concatenateError(err, stderr))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetPullRequestInfo generates and returns pull request information
 | 
					 | 
				
			||||||
// between base and head branches of repositories.
 | 
					 | 
				
			||||||
func (repo *Repository) GetPullRequestInfo(basePath, baseBranch, headBranch string) (_ *PullRequestInfo, err error) {
 | 
					 | 
				
			||||||
	// Add a temporary remote.
 | 
					 | 
				
			||||||
	tmpRemote := com.ToStr(time.Now().UnixNano())
 | 
					 | 
				
			||||||
	if err = repo.AddRemote(tmpRemote, basePath); err != nil {
 | 
					 | 
				
			||||||
		return nil, fmt.Errorf("AddRemote: %v", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer func() {
 | 
					 | 
				
			||||||
		repo.RemoveRemote(tmpRemote)
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	remoteBranch := "remotes/" + tmpRemote + "/" + baseBranch
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	prInfo := new(PullRequestInfo)
 | 
					 | 
				
			||||||
	prInfo.MergeBase, err = repo.GetMergeBase(remoteBranch, headBranch)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, fmt.Errorf("GetMergeBase: %v", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "log", prInfo.MergeBase+"..."+headBranch, prettyLogFormat)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, fmt.Errorf("list diff logs: %v", concatenateError(err, stderr))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	prInfo.Commits, err = parsePrettyFormatLog(repo, []byte(stdout))
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, fmt.Errorf("parsePrettyFormatLog: %v", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Count number of changed files.
 | 
					 | 
				
			||||||
	stdout, stderr, err = com.ExecCmdDir(repo.Path, "git", "diff", "--name-only", remoteBranch+"..."+headBranch)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, fmt.Errorf("list changed files: %v", concatenateError(err, stderr))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	prInfo.NumFiles = len(strings.Split(stdout, "\n")) - 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return prInfo, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetPatch generates and returns patch data between given branches.
 | 
					 | 
				
			||||||
func (repo *Repository) GetPatch(mergeBase, headBranch string) ([]byte, error) {
 | 
					 | 
				
			||||||
	stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "diff", "-p", "--binary", mergeBase, headBranch)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, concatenateError(err, string(stderr))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return stdout, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Merge merges pull request from head repository and branch.
 | 
					 | 
				
			||||||
func (repo *Repository) Merge(headRepoPath string, baseBranch, headBranch string) error {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,117 +0,0 @@
 | 
				
			|||||||
// 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/Unknwon/com"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func IsTagExist(repoPath, tagName string) bool {
 | 
					 | 
				
			||||||
	_, _, err := com.ExecCmdDir(repoPath, "git", "show-ref", "--verify", "refs/tags/"+tagName)
 | 
					 | 
				
			||||||
	return err == nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) IsTagExist(tagName string) bool {
 | 
					 | 
				
			||||||
	return IsTagExist(repo.Path, tagName)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) getTagsReversed() ([]string, error) {
 | 
					 | 
				
			||||||
	stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", "-l", "--sort=-v:refname")
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, concatenateError(err, stderr)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	tags := strings.Split(stdout, "\n")
 | 
					 | 
				
			||||||
	return tags[:len(tags)-1], nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetTags returns all tags of given repository.
 | 
					 | 
				
			||||||
func (repo *Repository) GetTags() ([]string, error) {
 | 
					 | 
				
			||||||
	if gitVer.AtLeast(MustParseVersion("2.0.0")) {
 | 
					 | 
				
			||||||
		return repo.getTagsReversed()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", "-l")
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, concatenateError(err, stderr)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	tags := strings.Split(stdout, "\n")
 | 
					 | 
				
			||||||
	return tags[:len(tags)-1], nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) CreateTag(tagName, idStr string) error {
 | 
					 | 
				
			||||||
	_, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", tagName, idStr)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return errors.New(stderr)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) getTag(id sha1) (*Tag, error) {
 | 
					 | 
				
			||||||
	if repo.tagCache != nil {
 | 
					 | 
				
			||||||
		if t, ok := repo.tagCache[id]; ok {
 | 
					 | 
				
			||||||
			return t, nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		repo.tagCache = make(map[sha1]*Tag, 10)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Get tag type.
 | 
					 | 
				
			||||||
	tp, stderr, err := com.ExecCmdDir(repo.Path, "git", "cat-file", "-t", id.String())
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, errors.New(stderr)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	tp = strings.TrimSpace(tp)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Tag is a commit.
 | 
					 | 
				
			||||||
	if ObjectType(tp) == COMMIT {
 | 
					 | 
				
			||||||
		tag := &Tag{
 | 
					 | 
				
			||||||
			ID:     id,
 | 
					 | 
				
			||||||
			Object: id,
 | 
					 | 
				
			||||||
			Type:   string(COMMIT),
 | 
					 | 
				
			||||||
			repo:   repo,
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		repo.tagCache[id] = tag
 | 
					 | 
				
			||||||
		return tag, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Tag with message.
 | 
					 | 
				
			||||||
	data, bytErr, err := com.ExecCmdDirBytes(repo.Path, "git", "cat-file", "-p", id.String())
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, errors.New(string(bytErr))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	tag, err := parseTagData(data)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	tag.ID = id
 | 
					 | 
				
			||||||
	tag.repo = repo
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	repo.tagCache[id] = tag
 | 
					 | 
				
			||||||
	return tag, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetTag returns a Git tag by given name.
 | 
					 | 
				
			||||||
func (repo *Repository) GetTag(tagName string) (*Tag, error) {
 | 
					 | 
				
			||||||
	stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "show-ref", "--tags", tagName)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, errors.New(stderr)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	id, err := NewIdFromString(strings.Split(stdout, " ")[0])
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	tag, err := repo.getTag(id)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	tag.Name = tagName
 | 
					 | 
				
			||||||
	return tag, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,32 +0,0 @@
 | 
				
			|||||||
// 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/Unknwon/com"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Find the tree object in the repository.
 | 
					 | 
				
			||||||
func (repo *Repository) GetTree(idStr string) (*Tree, error) {
 | 
					 | 
				
			||||||
	id, err := NewIdFromString(idStr)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return repo.getTree(id)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (repo *Repository) getTree(id sha1) (*Tree, error) {
 | 
					 | 
				
			||||||
	treePath := filepathFromSHA1(repo.Path, id.String())
 | 
					 | 
				
			||||||
	if !com.IsFile(treePath) {
 | 
					 | 
				
			||||||
		_, _, err := com.ExecCmdDir(repo.Path, "git", "ls-tree", id.String())
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, fmt.Errorf("repo.getTree: %v", ErrNotExist)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return NewTree(repo, id), nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,87 +0,0 @@
 | 
				
			|||||||
// 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"encoding/hex"
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	IDNotExist = errors.New("sha1 ID does not exist")
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type sha1 [20]byte
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Return true if s has the same sha1 as caller.
 | 
					 | 
				
			||||||
// Support 40-length-string, []byte, sha1
 | 
					 | 
				
			||||||
func (id sha1) Equal(s2 interface{}) bool {
 | 
					 | 
				
			||||||
	switch v := s2.(type) {
 | 
					 | 
				
			||||||
	case string:
 | 
					 | 
				
			||||||
		if len(v) != 40 {
 | 
					 | 
				
			||||||
			return false
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return v == id.String()
 | 
					 | 
				
			||||||
	case []byte:
 | 
					 | 
				
			||||||
		if len(v) != 20 {
 | 
					 | 
				
			||||||
			return false
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		for i, v := range v {
 | 
					 | 
				
			||||||
			if id[i] != v {
 | 
					 | 
				
			||||||
				return false
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case sha1:
 | 
					 | 
				
			||||||
		for i, v := range v {
 | 
					 | 
				
			||||||
			if id[i] != v {
 | 
					 | 
				
			||||||
				return false
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return true
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Return string (hex) representation of the Oid
 | 
					 | 
				
			||||||
func (s sha1) String() string {
 | 
					 | 
				
			||||||
	result := make([]byte, 0, 40)
 | 
					 | 
				
			||||||
	hexvalues := []byte("0123456789abcdef")
 | 
					 | 
				
			||||||
	for i := 0; i < 20; i++ {
 | 
					 | 
				
			||||||
		result = append(result, hexvalues[s[i]>>4])
 | 
					 | 
				
			||||||
		result = append(result, hexvalues[s[i]&0xf])
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return string(result)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Create a new sha1 from a 20 byte slice.
 | 
					 | 
				
			||||||
func NewId(b []byte) (sha1, error) {
 | 
					 | 
				
			||||||
	var id sha1
 | 
					 | 
				
			||||||
	if len(b) != 20 {
 | 
					 | 
				
			||||||
		return id, errors.New("Length must be 20")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for i := 0; i < 20; i++ {
 | 
					 | 
				
			||||||
		id[i] = b[i]
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return id, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Create a new sha1 from a Sha1 string of length 40.
 | 
					 | 
				
			||||||
func NewIdFromString(s string) (sha1, error) {
 | 
					 | 
				
			||||||
	s = strings.TrimSpace(s)
 | 
					 | 
				
			||||||
	var id sha1
 | 
					 | 
				
			||||||
	if len(s) != 40 {
 | 
					 | 
				
			||||||
		return id, fmt.Errorf("Length must be 40")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	b, err := hex.DecodeString(s)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return id, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return NewId(b)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,51 +0,0 @@
 | 
				
			|||||||
// 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Author and Committer information
 | 
					 | 
				
			||||||
type Signature struct {
 | 
					 | 
				
			||||||
	Email string
 | 
					 | 
				
			||||||
	Name  string
 | 
					 | 
				
			||||||
	When  time.Time
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Helper to get a signature from the commit line, which looks like these:
 | 
					 | 
				
			||||||
//     author Patrick Gundlach <gundlach@speedata.de> 1378823654 +0200
 | 
					 | 
				
			||||||
//     author Patrick Gundlach <gundlach@speedata.de> Thu, 07 Apr 2005 22:13:13 +0200
 | 
					 | 
				
			||||||
// but without the "author " at the beginning (this method should)
 | 
					 | 
				
			||||||
// be used for author and committer.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// FIXME: include timezone for timestamp!
 | 
					 | 
				
			||||||
func newSignatureFromCommitline(line []byte) (_ *Signature, err error) {
 | 
					 | 
				
			||||||
	sig := new(Signature)
 | 
					 | 
				
			||||||
	emailStart := bytes.IndexByte(line, '<')
 | 
					 | 
				
			||||||
	sig.Name = string(line[:emailStart-1])
 | 
					 | 
				
			||||||
	emailEnd := bytes.IndexByte(line, '>')
 | 
					 | 
				
			||||||
	sig.Email = string(line[emailStart+1 : emailEnd])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Check date format.
 | 
					 | 
				
			||||||
	firstChar := line[emailEnd+2]
 | 
					 | 
				
			||||||
	if firstChar >= 48 && firstChar <= 57 {
 | 
					 | 
				
			||||||
		timestop := bytes.IndexByte(line[emailEnd+2:], ' ')
 | 
					 | 
				
			||||||
		timestring := string(line[emailEnd+2 : emailEnd+2+timestop])
 | 
					 | 
				
			||||||
		seconds, err := strconv.ParseInt(timestring, 10, 64)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		sig.When = time.Unix(seconds, 0)
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		sig.When, err = time.Parse("Mon Jan _2 15:04:05 2006 -0700", string(line[emailEnd+2:]))
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return sig, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,20 +0,0 @@
 | 
				
			|||||||
// Copyright 2015 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	. "github.com/smartystreets/goconvey/convey"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func Test_newSignatureFromCommitline(t *testing.T) {
 | 
					 | 
				
			||||||
	Convey("Parse signature from commit line", t, func() {
 | 
					 | 
				
			||||||
		line := "Intern <intern@macbook-intern.(none)> 1445412825 +0200"
 | 
					 | 
				
			||||||
		sig, err := newSignatureFromCommitline([]byte(line))
 | 
					 | 
				
			||||||
		So(err, ShouldBeNil)
 | 
					 | 
				
			||||||
		So(sig, ShouldNotBeNil)
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,70 +0,0 @@
 | 
				
			|||||||
// 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/gogits/gogs/modules/setting"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type SubModule struct {
 | 
					 | 
				
			||||||
	Name string
 | 
					 | 
				
			||||||
	Url  string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SubModuleFile represents a file with submodule type.
 | 
					 | 
				
			||||||
type SubModuleFile struct {
 | 
					 | 
				
			||||||
	*Commit
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	refUrl string
 | 
					 | 
				
			||||||
	refId  string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewSubModuleFile(c *Commit, refUrl, refId string) *SubModuleFile {
 | 
					 | 
				
			||||||
	return &SubModuleFile{
 | 
					 | 
				
			||||||
		Commit: c,
 | 
					 | 
				
			||||||
		refUrl: refUrl,
 | 
					 | 
				
			||||||
		refId:  refId,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// RefUrl guesses and returns reference URL.
 | 
					 | 
				
			||||||
func (sf *SubModuleFile) RefUrl() string {
 | 
					 | 
				
			||||||
	if sf.refUrl == "" {
 | 
					 | 
				
			||||||
		return ""
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	url := strings.TrimSuffix(sf.refUrl, ".git")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// git://xxx/user/repo
 | 
					 | 
				
			||||||
	if strings.HasPrefix(url, "git://") {
 | 
					 | 
				
			||||||
		return "http://" + strings.TrimPrefix(url, "git://")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// http[s]://xxx/user/repo
 | 
					 | 
				
			||||||
	if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") {
 | 
					 | 
				
			||||||
		return url
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// sysuser@xxx:user/repo
 | 
					 | 
				
			||||||
	i := strings.Index(url, "@")
 | 
					 | 
				
			||||||
	j := strings.LastIndex(url, ":")
 | 
					 | 
				
			||||||
	if i > -1 && j > -1 {
 | 
					 | 
				
			||||||
		// fix problem with reverse proxy works only with local server
 | 
					 | 
				
			||||||
		if strings.Contains(setting.AppUrl, url[i+1:j]) {
 | 
					 | 
				
			||||||
			return setting.AppUrl + url[j+1:]
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			return "http://" + url[i+1:j] + "/" + url[j+1:]
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return url
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// RefId returns reference ID.
 | 
					 | 
				
			||||||
func (sf *SubModuleFile) RefId() string {
 | 
					 | 
				
			||||||
	return sf.refId
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,67 +0,0 @@
 | 
				
			|||||||
// 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Tag represents a Git tag.
 | 
					 | 
				
			||||||
type Tag struct {
 | 
					 | 
				
			||||||
	Name       string
 | 
					 | 
				
			||||||
	ID         sha1
 | 
					 | 
				
			||||||
	repo       *Repository
 | 
					 | 
				
			||||||
	Object     sha1 // The id of this commit object
 | 
					 | 
				
			||||||
	Type       string
 | 
					 | 
				
			||||||
	Tagger     *Signature
 | 
					 | 
				
			||||||
	TagMessage string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (tag *Tag) Commit() (*Commit, error) {
 | 
					 | 
				
			||||||
	return tag.repo.getCommit(tag.Object)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Parse commit information from the (uncompressed) raw
 | 
					 | 
				
			||||||
// data from the commit object.
 | 
					 | 
				
			||||||
// \n\n separate headers from message
 | 
					 | 
				
			||||||
func parseTagData(data []byte) (*Tag, error) {
 | 
					 | 
				
			||||||
	tag := new(Tag)
 | 
					 | 
				
			||||||
	// we now have the contents of the commit object. Let's investigate...
 | 
					 | 
				
			||||||
	nextline := 0
 | 
					 | 
				
			||||||
l:
 | 
					 | 
				
			||||||
	for {
 | 
					 | 
				
			||||||
		eol := bytes.IndexByte(data[nextline:], '\n')
 | 
					 | 
				
			||||||
		switch {
 | 
					 | 
				
			||||||
		case eol > 0:
 | 
					 | 
				
			||||||
			line := data[nextline : nextline+eol]
 | 
					 | 
				
			||||||
			spacepos := bytes.IndexByte(line, ' ')
 | 
					 | 
				
			||||||
			reftype := line[:spacepos]
 | 
					 | 
				
			||||||
			switch string(reftype) {
 | 
					 | 
				
			||||||
			case "object":
 | 
					 | 
				
			||||||
				id, err := NewIdFromString(string(line[spacepos+1:]))
 | 
					 | 
				
			||||||
				if err != nil {
 | 
					 | 
				
			||||||
					return nil, err
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				tag.Object = id
 | 
					 | 
				
			||||||
			case "type":
 | 
					 | 
				
			||||||
				// A commit can have one or more parents
 | 
					 | 
				
			||||||
				tag.Type = string(line[spacepos+1:])
 | 
					 | 
				
			||||||
			case "tagger":
 | 
					 | 
				
			||||||
				sig, err := newSignatureFromCommitline(line[spacepos+1:])
 | 
					 | 
				
			||||||
				if err != nil {
 | 
					 | 
				
			||||||
					return nil, err
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				tag.Tagger = sig
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			nextline += eol + 1
 | 
					 | 
				
			||||||
		case eol == 0:
 | 
					 | 
				
			||||||
			tag.TagMessage = string(data[nextline+1:])
 | 
					 | 
				
			||||||
			break l
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			break l
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return tag, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,157 +0,0 @@
 | 
				
			|||||||
// 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/Unknwon/com"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	ErrNotExist = errors.New("error not exist")
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A tree is a flat directory listing.
 | 
					 | 
				
			||||||
type Tree struct {
 | 
					 | 
				
			||||||
	ID   sha1
 | 
					 | 
				
			||||||
	repo *Repository
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// parent tree
 | 
					 | 
				
			||||||
	ptree *Tree
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	entries       Entries
 | 
					 | 
				
			||||||
	entriesParsed bool
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var escapeChar = []byte("\\")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func UnescapeChars(in []byte) []byte {
 | 
					 | 
				
			||||||
	if bytes.Index(in, escapeChar) == -1 {
 | 
					 | 
				
			||||||
		return in
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	endIdx := len(in) - 1
 | 
					 | 
				
			||||||
	isEscape := false
 | 
					 | 
				
			||||||
	out := make([]byte, 0, endIdx+1)
 | 
					 | 
				
			||||||
	for i := range in {
 | 
					 | 
				
			||||||
		if in[i] == '\\' && !isEscape {
 | 
					 | 
				
			||||||
			isEscape = true
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		isEscape = false
 | 
					 | 
				
			||||||
		out = append(out, in[i])
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return out
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Parse tree information from the (uncompressed) raw
 | 
					 | 
				
			||||||
// data from the tree object.
 | 
					 | 
				
			||||||
func parseTreeData(tree *Tree, data []byte) ([]*TreeEntry, error) {
 | 
					 | 
				
			||||||
	entries := make([]*TreeEntry, 0, 10)
 | 
					 | 
				
			||||||
	l := len(data)
 | 
					 | 
				
			||||||
	pos := 0
 | 
					 | 
				
			||||||
	for pos < l {
 | 
					 | 
				
			||||||
		entry := new(TreeEntry)
 | 
					 | 
				
			||||||
		entry.ptree = tree
 | 
					 | 
				
			||||||
		step := 6
 | 
					 | 
				
			||||||
		switch string(data[pos : pos+step]) {
 | 
					 | 
				
			||||||
		case "100644":
 | 
					 | 
				
			||||||
			entry.mode = ModeBlob
 | 
					 | 
				
			||||||
			entry.Type = BLOB
 | 
					 | 
				
			||||||
		case "100755":
 | 
					 | 
				
			||||||
			entry.mode = ModeExec
 | 
					 | 
				
			||||||
			entry.Type = BLOB
 | 
					 | 
				
			||||||
		case "120000":
 | 
					 | 
				
			||||||
			entry.mode = ModeSymlink
 | 
					 | 
				
			||||||
			entry.Type = BLOB
 | 
					 | 
				
			||||||
		case "160000":
 | 
					 | 
				
			||||||
			entry.mode = ModeCommit
 | 
					 | 
				
			||||||
			entry.Type = COMMIT
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			step = 8
 | 
					 | 
				
			||||||
		case "040000":
 | 
					 | 
				
			||||||
			entry.mode = ModeTree
 | 
					 | 
				
			||||||
			entry.Type = TREE
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			return nil, errors.New("unknown type: " + string(data[pos:pos+step]))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		pos += step + 6 // Skip string type of entry type.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		step = 40
 | 
					 | 
				
			||||||
		id, err := NewIdFromString(string(data[pos : pos+step]))
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		entry.ID = id
 | 
					 | 
				
			||||||
		pos += step + 1 // Skip half of sha1.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		step = bytes.IndexByte(data[pos:], '\n')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// In case entry name is surrounded by double quotes(it happens only in git-shell).
 | 
					 | 
				
			||||||
		if data[pos] == '"' {
 | 
					 | 
				
			||||||
			entry.name = string(UnescapeChars(data[pos+1 : pos+step-1]))
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			entry.name = string(data[pos : pos+step])
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		pos += step + 1
 | 
					 | 
				
			||||||
		entries = append(entries, entry)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return entries, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *Tree) SubTree(rpath string) (*Tree, error) {
 | 
					 | 
				
			||||||
	if len(rpath) == 0 {
 | 
					 | 
				
			||||||
		return t, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	paths := strings.Split(rpath, "/")
 | 
					 | 
				
			||||||
	var err error
 | 
					 | 
				
			||||||
	var g = t
 | 
					 | 
				
			||||||
	var p = t
 | 
					 | 
				
			||||||
	var te *TreeEntry
 | 
					 | 
				
			||||||
	for _, name := range paths {
 | 
					 | 
				
			||||||
		te, err = p.GetTreeEntryByPath(name)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		g, err = t.repo.getTree(te.ID)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		g.ptree = p
 | 
					 | 
				
			||||||
		p = g
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return g, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *Tree) ListEntries(relpath string) (Entries, error) {
 | 
					 | 
				
			||||||
	if t.entriesParsed {
 | 
					 | 
				
			||||||
		return t.entries, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	t.entriesParsed = true
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	stdout, stderr, err := com.ExecCmdDirBytes(t.repo.Path,
 | 
					 | 
				
			||||||
		"git", "ls-tree", t.ID.String())
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		if strings.Contains(err.Error(), "exit status 128") {
 | 
					 | 
				
			||||||
			return nil, errors.New(strings.TrimSpace(string(stderr)))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	t.entries, err = parseTreeData(t, stdout)
 | 
					 | 
				
			||||||
	return t.entries, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewTree(repo *Repository, id sha1) *Tree {
 | 
					 | 
				
			||||||
	tree := new(Tree)
 | 
					 | 
				
			||||||
	tree.ID = id
 | 
					 | 
				
			||||||
	tree.repo = repo
 | 
					 | 
				
			||||||
	return tree
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,59 +0,0 @@
 | 
				
			|||||||
// 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"path"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *Tree) GetTreeEntryByPath(relpath string) (*TreeEntry, error) {
 | 
					 | 
				
			||||||
	if len(relpath) == 0 {
 | 
					 | 
				
			||||||
		return &TreeEntry{
 | 
					 | 
				
			||||||
			ID:   t.ID,
 | 
					 | 
				
			||||||
			Type: TREE,
 | 
					 | 
				
			||||||
			mode: ModeTree,
 | 
					 | 
				
			||||||
		}, nil
 | 
					 | 
				
			||||||
		// return nil, fmt.Errorf("GetTreeEntryByPath(empty relpath): %v", ErrNotExist)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	relpath = path.Clean(relpath)
 | 
					 | 
				
			||||||
	parts := strings.Split(relpath, "/")
 | 
					 | 
				
			||||||
	var err error
 | 
					 | 
				
			||||||
	tree := t
 | 
					 | 
				
			||||||
	for i, name := range parts {
 | 
					 | 
				
			||||||
		if i == len(parts)-1 {
 | 
					 | 
				
			||||||
			entries, err := tree.ListEntries(path.Dir(relpath))
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				return nil, err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			for _, v := range entries {
 | 
					 | 
				
			||||||
				if v.name == name {
 | 
					 | 
				
			||||||
					return v, nil
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			tree, err = tree.SubTree(name)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				return nil, err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil, fmt.Errorf("GetTreeEntryByPath: %v", ErrNotExist)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *Tree) GetBlobByPath(rpath string) (*Blob, error) {
 | 
					 | 
				
			||||||
	entry, err := t.GetTreeEntryByPath(rpath)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !entry.IsDir() {
 | 
					 | 
				
			||||||
		return entry.Blob(), nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil, ErrNotExist
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,113 +0,0 @@
 | 
				
			|||||||
// 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"sort"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/Unknwon/com"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type EntryMode int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// There are only a few file modes in Git. They look like unix file modes, but they can only be
 | 
					 | 
				
			||||||
// one of these.
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	ModeBlob    EntryMode = 0100644
 | 
					 | 
				
			||||||
	ModeExec    EntryMode = 0100755
 | 
					 | 
				
			||||||
	ModeSymlink EntryMode = 0120000
 | 
					 | 
				
			||||||
	ModeCommit  EntryMode = 0160000
 | 
					 | 
				
			||||||
	ModeTree    EntryMode = 0040000
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type TreeEntry struct {
 | 
					 | 
				
			||||||
	ID   sha1
 | 
					 | 
				
			||||||
	Type ObjectType
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mode EntryMode
 | 
					 | 
				
			||||||
	name string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ptree *Tree
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	commited bool
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	size  int64
 | 
					 | 
				
			||||||
	sized bool
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (te *TreeEntry) Name() string {
 | 
					 | 
				
			||||||
	return te.name
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (te *TreeEntry) Size() int64 {
 | 
					 | 
				
			||||||
	if te.IsDir() {
 | 
					 | 
				
			||||||
		return 0
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if te.sized {
 | 
					 | 
				
			||||||
		return te.size
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	stdout, _, err := com.ExecCmdDir(te.ptree.repo.Path, "git", "cat-file", "-s", te.ID.String())
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return 0
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	te.sized = true
 | 
					 | 
				
			||||||
	te.size = com.StrTo(strings.TrimSpace(stdout)).MustInt64()
 | 
					 | 
				
			||||||
	return te.size
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (te *TreeEntry) IsSubModule() bool {
 | 
					 | 
				
			||||||
	return te.mode == ModeCommit
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (te *TreeEntry) IsDir() bool {
 | 
					 | 
				
			||||||
	return te.mode == ModeTree
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (te *TreeEntry) EntryMode() EntryMode {
 | 
					 | 
				
			||||||
	return te.mode
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (te *TreeEntry) Blob() *Blob {
 | 
					 | 
				
			||||||
	return &Blob{
 | 
					 | 
				
			||||||
		repo:      te.ptree.repo,
 | 
					 | 
				
			||||||
		TreeEntry: te,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type Entries []*TreeEntry
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var sorter = []func(t1, t2 *TreeEntry) bool{
 | 
					 | 
				
			||||||
	func(t1, t2 *TreeEntry) bool {
 | 
					 | 
				
			||||||
		return (t1.IsDir() || t1.IsSubModule()) && !t2.IsDir() && !t2.IsSubModule()
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	func(t1, t2 *TreeEntry) bool {
 | 
					 | 
				
			||||||
		return t1.name < t2.name
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (bs Entries) Len() int      { return len(bs) }
 | 
					 | 
				
			||||||
func (bs Entries) Swap(i, j int) { bs[i], bs[j] = bs[j], bs[i] }
 | 
					 | 
				
			||||||
func (bs Entries) Less(i, j int) bool {
 | 
					 | 
				
			||||||
	t1, t2 := bs[i], bs[j]
 | 
					 | 
				
			||||||
	var k int
 | 
					 | 
				
			||||||
	for k = 0; k < len(sorter)-1; k++ {
 | 
					 | 
				
			||||||
		sort := sorter[k]
 | 
					 | 
				
			||||||
		switch {
 | 
					 | 
				
			||||||
		case sort(t1, t2):
 | 
					 | 
				
			||||||
			return true
 | 
					 | 
				
			||||||
		case sort(t2, t1):
 | 
					 | 
				
			||||||
			return false
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return sorter[k](t1, t2)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (bs Entries) Sort() {
 | 
					 | 
				
			||||||
	sort.Sort(bs)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,82 +0,0 @@
 | 
				
			|||||||
// 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"container/list"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const prettyLogFormat = `--pretty=format:%H`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func parsePrettyFormatLog(repo *Repository, logByts []byte) (*list.List, error) {
 | 
					 | 
				
			||||||
	l := list.New()
 | 
					 | 
				
			||||||
	if len(logByts) == 0 {
 | 
					 | 
				
			||||||
		return l, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	parts := bytes.Split(logByts, []byte{'\n'})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, commitId := range parts {
 | 
					 | 
				
			||||||
		commit, err := repo.GetCommit(string(commitId))
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		l.PushBack(commit)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return l, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func RefEndName(refStr string) string {
 | 
					 | 
				
			||||||
	if strings.HasPrefix(refStr, "refs/heads/") {
 | 
					 | 
				
			||||||
		// trim the "refs/heads/"
 | 
					 | 
				
			||||||
		return refStr[len("refs/heads/"):]
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	index := strings.LastIndex(refStr, "/")
 | 
					 | 
				
			||||||
	if index != -1 {
 | 
					 | 
				
			||||||
		return refStr[index+1:]
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return refStr
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// If the object is stored in its own file (i.e not in a pack file),
 | 
					 | 
				
			||||||
// this function returns the full path to the object file.
 | 
					 | 
				
			||||||
// It does not test if the file exists.
 | 
					 | 
				
			||||||
func filepathFromSHA1(rootdir, sha1 string) string {
 | 
					 | 
				
			||||||
	return filepath.Join(rootdir, "objects", sha1[:2], sha1[2:])
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// isDir returns true if given path is a directory,
 | 
					 | 
				
			||||||
// or returns false when it's a file or does not exist.
 | 
					 | 
				
			||||||
func isDir(dir string) bool {
 | 
					 | 
				
			||||||
	f, e := os.Stat(dir)
 | 
					 | 
				
			||||||
	if e != nil {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return f.IsDir()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// isFile returns true if given path is a file,
 | 
					 | 
				
			||||||
// or returns false when it's a directory or does not exist.
 | 
					 | 
				
			||||||
func isFile(filePath string) bool {
 | 
					 | 
				
			||||||
	f, e := os.Stat(filePath)
 | 
					 | 
				
			||||||
	if e != nil {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return !f.IsDir()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func concatenateError(err error, stderr string) error {
 | 
					 | 
				
			||||||
	if len(stderr) == 0 {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return fmt.Errorf("%v: %s", err, stderr)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,104 +0,0 @@
 | 
				
			|||||||
// 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 git
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/Unknwon/com"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	// Cached Git version.
 | 
					 | 
				
			||||||
	gitVer *Version
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Version represents version of Git.
 | 
					 | 
				
			||||||
type Version struct {
 | 
					 | 
				
			||||||
	Major, Minor, Patch int
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ParseVersion(verStr string) (*Version, error) {
 | 
					 | 
				
			||||||
	infos := strings.Split(verStr, ".")
 | 
					 | 
				
			||||||
	if len(infos) < 3 {
 | 
					 | 
				
			||||||
		return nil, errors.New("incorrect version input")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	v := &Version{}
 | 
					 | 
				
			||||||
	for i, s := range infos {
 | 
					 | 
				
			||||||
		switch i {
 | 
					 | 
				
			||||||
		case 0:
 | 
					 | 
				
			||||||
			v.Major, _ = com.StrTo(s).Int()
 | 
					 | 
				
			||||||
		case 1:
 | 
					 | 
				
			||||||
			v.Minor, _ = com.StrTo(s).Int()
 | 
					 | 
				
			||||||
		case 2:
 | 
					 | 
				
			||||||
			v.Patch, _ = com.StrTo(strings.TrimSpace(s)).Int()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return v, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func MustParseVersion(verStr string) *Version {
 | 
					 | 
				
			||||||
	v, _ := ParseVersion(verStr)
 | 
					 | 
				
			||||||
	return v
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Compare compares two versions,
 | 
					 | 
				
			||||||
// it returns 1 if original is greater, -1 if original is smaller, 0 if equal.
 | 
					 | 
				
			||||||
func (v *Version) Compare(that *Version) int {
 | 
					 | 
				
			||||||
	if v.Major > that.Major {
 | 
					 | 
				
			||||||
		return 1
 | 
					 | 
				
			||||||
	} else if v.Major < that.Major {
 | 
					 | 
				
			||||||
		return -1
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if v.Minor > that.Minor {
 | 
					 | 
				
			||||||
		return 1
 | 
					 | 
				
			||||||
	} else if v.Minor < that.Minor {
 | 
					 | 
				
			||||||
		return -1
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if v.Patch > that.Patch {
 | 
					 | 
				
			||||||
		return 1
 | 
					 | 
				
			||||||
	} else if v.Patch < that.Patch {
 | 
					 | 
				
			||||||
		return -1
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (v *Version) LessThan(that *Version) bool {
 | 
					 | 
				
			||||||
	return v.Compare(that) < 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (v *Version) AtLeast(that *Version) bool {
 | 
					 | 
				
			||||||
	return v.Compare(that) >= 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (v *Version) String() string {
 | 
					 | 
				
			||||||
	return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetVersion returns current Git version installed.
 | 
					 | 
				
			||||||
func GetVersion() (*Version, error) {
 | 
					 | 
				
			||||||
	if gitVer != nil {
 | 
					 | 
				
			||||||
		return gitVer, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	stdout, stderr, err := com.ExecCmd("git", "version")
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, errors.New(stderr)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	infos := strings.Split(stdout, " ")
 | 
					 | 
				
			||||||
	if len(infos) < 3 {
 | 
					 | 
				
			||||||
		return nil, errors.New("not enough output")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	gitVer, err = ParseVersion(infos[2])
 | 
					 | 
				
			||||||
	return gitVer, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -18,10 +18,11 @@ import (
 | 
				
			|||||||
	"github.com/go-macaron/session"
 | 
						"github.com/go-macaron/session"
 | 
				
			||||||
	"gopkg.in/macaron.v1"
 | 
						"gopkg.in/macaron.v1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/git-shell"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/models"
 | 
						"github.com/gogits/gogs/models"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/auth"
 | 
						"github.com/gogits/gogs/modules/auth"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/base"
 | 
						"github.com/gogits/gogs/modules/base"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/git"
 | 
					 | 
				
			||||||
	"github.com/gogits/gogs/modules/log"
 | 
						"github.com/gogits/gogs/modules/log"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/setting"
 | 
						"github.com/gogits/gogs/modules/setting"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -43,7 +44,7 @@ type RepoContext struct {
 | 
				
			|||||||
	CommitID     string
 | 
						CommitID     string
 | 
				
			||||||
	RepoLink     string
 | 
						RepoLink     string
 | 
				
			||||||
	CloneLink    models.CloneLink
 | 
						CloneLink    models.CloneLink
 | 
				
			||||||
	CommitsCount int
 | 
						CommitsCount int64
 | 
				
			||||||
	Mirror       *models.Mirror
 | 
						Mirror       *models.Mirror
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,8 +11,9 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"gopkg.in/macaron.v1"
 | 
						"gopkg.in/macaron.v1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/git-shell"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/models"
 | 
						"github.com/gogits/gogs/models"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/git"
 | 
					 | 
				
			||||||
	"github.com/gogits/gogs/modules/log"
 | 
						"github.com/gogits/gogs/modules/log"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/setting"
 | 
						"github.com/gogits/gogs/modules/setting"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -257,9 +258,9 @@ func RepoRef() macaron.Handler {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				refName = brs[0]
 | 
									refName = brs[0]
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommitOfBranch(refName)
 | 
								ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				ctx.Handle(500, "GetCommitOfBranch", err)
 | 
									ctx.Handle(500, "GetBranchCommit", err)
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
 | 
								ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
 | 
				
			||||||
@@ -288,18 +289,18 @@ func RepoRef() macaron.Handler {
 | 
				
			|||||||
			if ctx.Repo.GitRepo.IsBranchExist(refName) {
 | 
								if ctx.Repo.GitRepo.IsBranchExist(refName) {
 | 
				
			||||||
				ctx.Repo.IsViewBranch = true
 | 
									ctx.Repo.IsViewBranch = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommitOfBranch(refName)
 | 
									ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					ctx.Handle(500, "GetCommitOfBranch", err)
 | 
										ctx.Handle(500, "GetBranchCommit", err)
 | 
				
			||||||
					return
 | 
										return
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
 | 
									ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			} else if ctx.Repo.GitRepo.IsTagExist(refName) {
 | 
								} else if ctx.Repo.GitRepo.IsTagExist(refName) {
 | 
				
			||||||
				ctx.Repo.IsViewTag = true
 | 
									ctx.Repo.IsViewTag = true
 | 
				
			||||||
				ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommitOfTag(refName)
 | 
									ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetTagCommit(refName)
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					ctx.Handle(500, "GetCommitOfTag", err)
 | 
										ctx.Handle(500, "GetTagCommit", err)
 | 
				
			||||||
					return
 | 
										return
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
 | 
									ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,8 +5,9 @@
 | 
				
			|||||||
package repo
 | 
					package repo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogits/git-shell"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/models"
 | 
						"github.com/gogits/gogs/models"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/git"
 | 
					 | 
				
			||||||
	"github.com/gogits/gogs/modules/middleware"
 | 
						"github.com/gogits/gogs/modules/middleware"
 | 
				
			||||||
	"github.com/gogits/gogs/routers/repo"
 | 
						"github.com/gogits/gogs/routers/repo"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -20,7 +21,7 @@ func GetRawFile(ctx *middleware.Context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	blob, err := ctx.Repo.Commit.GetBlobByPath(ctx.Repo.TreeName)
 | 
						blob, err := ctx.Repo.Commit.GetBlobByPath(ctx.Repo.TreeName)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		if err == git.ErrNotExist {
 | 
							if git.IsErrNotExist(err) {
 | 
				
			||||||
			ctx.Error(404)
 | 
								ctx.Error(404)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			ctx.APIError(500, "GetBlobByPath", err)
 | 
								ctx.APIError(500, "GetBlobByPath", err)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,9 +10,10 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/Unknwon/paginater"
 | 
						"github.com/Unknwon/paginater"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/git-shell"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/models"
 | 
						"github.com/gogits/gogs/models"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/base"
 | 
						"github.com/gogits/gogs/modules/base"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/git"
 | 
					 | 
				
			||||||
	"github.com/gogits/gogs/modules/middleware"
 | 
						"github.com/gogits/gogs/modules/middleware"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/setting"
 | 
						"github.com/gogits/gogs/modules/setting"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -55,7 +56,7 @@ func Commits(ctx *middleware.Context) {
 | 
				
			|||||||
	if page <= 1 {
 | 
						if page <= 1 {
 | 
				
			||||||
		page = 1
 | 
							page = 1
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.Data["Page"] = paginater.New(commitsCount, git.CommitsRangeSize, page, 5)
 | 
						ctx.Data["Page"] = paginater.New(int(commitsCount), git.CommitsRangeSize, page, 5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Both `git log branchName` and `git log commitId` work.
 | 
						// Both `git log branchName` and `git log commitId` work.
 | 
				
			||||||
	commits, err := ctx.Repo.Commit.CommitsByRange(page)
 | 
						commits, err := ctx.Repo.Commit.CommitsByRange(page)
 | 
				
			||||||
@@ -123,7 +124,7 @@ func FileHistory(ctx *middleware.Context) {
 | 
				
			|||||||
	if page <= 1 {
 | 
						if page <= 1 {
 | 
				
			||||||
		page = 1
 | 
							page = 1
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.Data["Page"] = paginater.New(commitsCount, git.CommitsRangeSize, page, 5)
 | 
						ctx.Data["Page"] = paginater.New(int(commitsCount), git.CommitsRangeSize, page, 5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	commits, err := ctx.Repo.GitRepo.CommitsByFileAndRange(branchName, fileName, page)
 | 
						commits, err := ctx.Repo.GitRepo.CommitsByFileAndRange(branchName, fileName, page)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -159,7 +160,7 @@ func Diff(ctx *middleware.Context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	parents := make([]string, commit.ParentCount())
 | 
						parents := make([]string, commit.ParentCount())
 | 
				
			||||||
	for i := 0; i < commit.ParentCount(); i++ {
 | 
						for i := 0; i < commit.ParentCount(); i++ {
 | 
				
			||||||
		sha, err := commit.ParentId(i)
 | 
							sha, err := commit.ParentID(i)
 | 
				
			||||||
		parents[i] = sha.String()
 | 
							parents[i] = sha.String()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			ctx.Handle(404, "repo.Diff", err)
 | 
								ctx.Handle(404, "repo.Diff", err)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,8 +8,9 @@ import (
 | 
				
			|||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"path"
 | 
						"path"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/git-shell"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/modules/base"
 | 
						"github.com/gogits/gogs/modules/base"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/git"
 | 
					 | 
				
			||||||
	"github.com/gogits/gogs/modules/middleware"
 | 
						"github.com/gogits/gogs/modules/middleware"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -45,7 +46,7 @@ func ServeBlob(ctx *middleware.Context, blob *git.Blob) error {
 | 
				
			|||||||
func SingleDownload(ctx *middleware.Context) {
 | 
					func SingleDownload(ctx *middleware.Context) {
 | 
				
			||||||
	blob, err := ctx.Repo.Commit.GetBlobByPath(ctx.Repo.TreeName)
 | 
						blob, err := ctx.Repo.Commit.GetBlobByPath(ctx.Repo.TreeName)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		if err == git.ErrNotExist {
 | 
							if git.IsErrNotExist(err) {
 | 
				
			||||||
			ctx.Handle(404, "GetBlobByPath", nil)
 | 
								ctx.Handle(404, "GetBlobByPath", nil)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			ctx.Handle(500, "GetBlobByPath", err)
 | 
								ctx.Handle(500, "GetBlobByPath", err)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,10 +12,11 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/Unknwon/com"
 | 
						"github.com/Unknwon/com"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/git-shell"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/models"
 | 
						"github.com/gogits/gogs/models"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/auth"
 | 
						"github.com/gogits/gogs/modules/auth"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/base"
 | 
						"github.com/gogits/gogs/modules/base"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/git"
 | 
					 | 
				
			||||||
	"github.com/gogits/gogs/modules/log"
 | 
						"github.com/gogits/gogs/modules/log"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/middleware"
 | 
						"github.com/gogits/gogs/modules/middleware"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/setting"
 | 
						"github.com/gogits/gogs/modules/setting"
 | 
				
			||||||
@@ -328,9 +329,9 @@ func ViewPullFiles(ctx *middleware.Context) {
 | 
				
			|||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		headCommitID, err := headGitRepo.GetCommitIdOfBranch(pull.HeadBranch)
 | 
							headCommitID, err := headGitRepo.GetBranchCommitID(pull.HeadBranch)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			ctx.Handle(500, "GetCommitIdOfBranch", err)
 | 
								ctx.Handle(500, "GetBranchCommitID", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -492,9 +493,9 @@ func PrepareCompareDiff(
 | 
				
			|||||||
	// Get diff information.
 | 
						// Get diff information.
 | 
				
			||||||
	ctx.Data["CommitRepoLink"] = headRepo.RepoLink()
 | 
						ctx.Data["CommitRepoLink"] = headRepo.RepoLink()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	headCommitID, err := headGitRepo.GetCommitIdOfBranch(headBranch)
 | 
						headCommitID, err := headGitRepo.GetBranchCommitID(headBranch)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Handle(500, "GetCommitIdOfBranch", err)
 | 
							ctx.Handle(500, "GetBranchCommitID", err)
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.Data["AfterCommitID"] = headCommitID
 | 
						ctx.Data["AfterCommitID"] = headCommitID
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,7 +34,7 @@ func Releases(ctx *middleware.Context) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Temproray cache commits count of used branches to speed up.
 | 
						// Temproray cache commits count of used branches to speed up.
 | 
				
			||||||
	countCache := make(map[string]int)
 | 
						countCache := make(map[string]int64)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tags := make([]*models.Release, len(rawTags))
 | 
						tags := make([]*models.Release, len(rawTags))
 | 
				
			||||||
	for i, rawTag := range rawTags {
 | 
						for i, rawTag := range rawTags {
 | 
				
			||||||
@@ -45,7 +45,7 @@ func Releases(ctx *middleware.Context) {
 | 
				
			|||||||
			if rel.TagName == rawTag {
 | 
								if rel.TagName == rawTag {
 | 
				
			||||||
				rel.Publisher, err = models.GetUserByID(rel.PublisherID)
 | 
									rel.Publisher, err = models.GetUserByID(rel.PublisherID)
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					ctx.Handle(500, "GetUserById", err)
 | 
										ctx.Handle(500, "GetUserByID", err)
 | 
				
			||||||
					return
 | 
										return
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				// FIXME: duplicated code.
 | 
									// FIXME: duplicated code.
 | 
				
			||||||
@@ -53,14 +53,14 @@ func Releases(ctx *middleware.Context) {
 | 
				
			|||||||
				if ctx.Repo.BranchName != rel.Target {
 | 
									if ctx.Repo.BranchName != rel.Target {
 | 
				
			||||||
					// Get count if not exists.
 | 
										// Get count if not exists.
 | 
				
			||||||
					if _, ok := countCache[rel.Target]; !ok {
 | 
										if _, ok := countCache[rel.Target]; !ok {
 | 
				
			||||||
						commit, err := ctx.Repo.GitRepo.GetCommitOfBranch(ctx.Repo.BranchName)
 | 
											commit, err := ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.BranchName)
 | 
				
			||||||
						if err != nil {
 | 
											if err != nil {
 | 
				
			||||||
							ctx.Handle(500, "GetCommitOfBranch", err)
 | 
												ctx.Handle(500, "GetBranchCommit", err)
 | 
				
			||||||
							return
 | 
												return
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						countCache[ctx.Repo.BranchName], err = commit.CommitsCount()
 | 
											countCache[ctx.Repo.BranchName], err = commit.CommitsCount()
 | 
				
			||||||
						if err != nil {
 | 
											if err != nil {
 | 
				
			||||||
							ctx.Handle(500, "CommitsCount2", err)
 | 
												ctx.Handle(500, "CommitsCount", err)
 | 
				
			||||||
							return
 | 
												return
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
@@ -77,9 +77,9 @@ func Releases(ctx *middleware.Context) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if tags[i] == nil {
 | 
							if tags[i] == nil {
 | 
				
			||||||
			commit, err := ctx.Repo.GitRepo.GetCommitOfTag(rawTag)
 | 
								commit, err := ctx.Repo.GitRepo.GetTagCommit(rawTag)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				ctx.Handle(500, "GetCommitOfTag2", err)
 | 
									ctx.Handle(500, "GetTagCommit", err)
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -89,7 +89,7 @@ func Releases(ctx *middleware.Context) {
 | 
				
			|||||||
				Sha1:    commit.ID.String(),
 | 
									Sha1:    commit.ID.String(),
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			tags[i].NumCommits, err = ctx.Repo.GitRepo.CommitsCount(commit.ID.String())
 | 
								tags[i].NumCommits, err = commit.CommitsCount()
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				ctx.Handle(500, "CommitsCount", err)
 | 
									ctx.Handle(500, "CommitsCount", err)
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
@@ -105,7 +105,7 @@ func Releases(ctx *middleware.Context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		rel.Publisher, err = models.GetUserByID(rel.PublisherID)
 | 
							rel.Publisher, err = models.GetUserByID(rel.PublisherID)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			ctx.Handle(500, "GetUserById", err)
 | 
								ctx.Handle(500, "GetUserByID", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// FIXME: duplicated code.
 | 
							// FIXME: duplicated code.
 | 
				
			||||||
@@ -113,14 +113,14 @@ func Releases(ctx *middleware.Context) {
 | 
				
			|||||||
		if ctx.Repo.BranchName != rel.Target {
 | 
							if ctx.Repo.BranchName != rel.Target {
 | 
				
			||||||
			// Get count if not exists.
 | 
								// Get count if not exists.
 | 
				
			||||||
			if _, ok := countCache[rel.Target]; !ok {
 | 
								if _, ok := countCache[rel.Target]; !ok {
 | 
				
			||||||
				commit, err := ctx.Repo.GitRepo.GetCommitOfBranch(ctx.Repo.BranchName)
 | 
									commit, err := ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.BranchName)
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					ctx.Handle(500, "GetCommitOfBranch", err)
 | 
										ctx.Handle(500, "GetBranchCommit", err)
 | 
				
			||||||
					return
 | 
										return
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				countCache[ctx.Repo.BranchName], err = commit.CommitsCount()
 | 
									countCache[ctx.Repo.BranchName], err = commit.CommitsCount()
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					ctx.Handle(500, "CommitsCount2", err)
 | 
										ctx.Handle(500, "CommitsCount", err)
 | 
				
			||||||
					return
 | 
										return
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -158,9 +158,9 @@ func NewReleasePost(ctx *middleware.Context, form auth.NewReleaseForm) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	commit, err := ctx.Repo.GitRepo.GetCommitOfBranch(form.Target)
 | 
						commit, err := ctx.Repo.GitRepo.GetBranchCommit(form.Target)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Handle(500, "GetCommitOfBranch", err)
 | 
							ctx.Handle(500, "GetBranchCommit", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,10 +12,11 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/Unknwon/com"
 | 
						"github.com/Unknwon/com"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/git-shell"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/models"
 | 
						"github.com/gogits/gogs/models"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/auth"
 | 
						"github.com/gogits/gogs/modules/auth"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/base"
 | 
						"github.com/gogits/gogs/modules/base"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/git"
 | 
					 | 
				
			||||||
	"github.com/gogits/gogs/modules/log"
 | 
						"github.com/gogits/gogs/modules/log"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/middleware"
 | 
						"github.com/gogits/gogs/modules/middleware"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/setting"
 | 
						"github.com/gogits/gogs/modules/setting"
 | 
				
			||||||
@@ -294,21 +295,21 @@ func Download(ctx *middleware.Context) {
 | 
				
			|||||||
	)
 | 
						)
 | 
				
			||||||
	gitRepo := ctx.Repo.GitRepo
 | 
						gitRepo := ctx.Repo.GitRepo
 | 
				
			||||||
	if gitRepo.IsBranchExist(refName) {
 | 
						if gitRepo.IsBranchExist(refName) {
 | 
				
			||||||
		commit, err = gitRepo.GetCommitOfBranch(refName)
 | 
							commit, err = gitRepo.GetBranchCommit(refName)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			ctx.Handle(500, "Download", err)
 | 
								ctx.Handle(500, "GetBranchCommit", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else if gitRepo.IsTagExist(refName) {
 | 
						} else if gitRepo.IsTagExist(refName) {
 | 
				
			||||||
		commit, err = gitRepo.GetCommitOfTag(refName)
 | 
							commit, err = gitRepo.GetTagCommit(refName)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			ctx.Handle(500, "Download", err)
 | 
								ctx.Handle(500, "GetTagCommit", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else if len(refName) == 40 {
 | 
						} else if len(refName) == 40 {
 | 
				
			||||||
		commit, err = gitRepo.GetCommit(refName)
 | 
							commit, err = gitRepo.GetCommit(refName)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			ctx.Handle(404, "Download", nil)
 | 
								ctx.Handle(404, "GetCommit", nil)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,10 +8,11 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/git-shell"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/models"
 | 
						"github.com/gogits/gogs/models"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/auth"
 | 
						"github.com/gogits/gogs/modules/auth"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/base"
 | 
						"github.com/gogits/gogs/modules/base"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/git"
 | 
					 | 
				
			||||||
	"github.com/gogits/gogs/modules/log"
 | 
						"github.com/gogits/gogs/modules/log"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/mailer"
 | 
						"github.com/gogits/gogs/modules/mailer"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/middleware"
 | 
						"github.com/gogits/gogs/modules/middleware"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,9 +13,10 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/Unknwon/paginater"
 | 
						"github.com/Unknwon/paginater"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/git-shell"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/models"
 | 
						"github.com/gogits/gogs/models"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/base"
 | 
						"github.com/gogits/gogs/modules/base"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/git"
 | 
					 | 
				
			||||||
	"github.com/gogits/gogs/modules/log"
 | 
						"github.com/gogits/gogs/modules/log"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/middleware"
 | 
						"github.com/gogits/gogs/modules/middleware"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/template"
 | 
						"github.com/gogits/gogs/modules/template"
 | 
				
			||||||
@@ -59,7 +60,7 @@ func Home(ctx *middleware.Context) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	entry, err := ctx.Repo.Commit.GetTreeEntryByPath(treename)
 | 
						entry, err := ctx.Repo.Commit.GetTreeEntryByPath(treename)
 | 
				
			||||||
	if err != nil && err != git.ErrNotExist {
 | 
						if err != nil && git.IsErrNotExist(err) {
 | 
				
			||||||
		ctx.Handle(404, "GetTreeEntryByPath", err)
 | 
							ctx.Handle(404, "GetTreeEntryByPath", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -126,7 +127,7 @@ func Home(ctx *middleware.Context) {
 | 
				
			|||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		entries, err := tree.ListEntries(treename)
 | 
							entries, err := tree.ListEntries()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			ctx.Handle(500, "ListEntries", err)
 | 
								ctx.Handle(500, "ListEntries", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
@@ -135,10 +136,10 @@ func Home(ctx *middleware.Context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		files := make([][]interface{}, 0, len(entries))
 | 
							files := make([][]interface{}, 0, len(entries))
 | 
				
			||||||
		for _, te := range entries {
 | 
							for _, te := range entries {
 | 
				
			||||||
			if te.Type != git.COMMIT {
 | 
								if te.Type != git.OBJECT_COMMIT {
 | 
				
			||||||
				c, err := ctx.Repo.Commit.GetCommitOfRelPath(filepath.Join(treePath, te.Name()))
 | 
									c, err := ctx.Repo.Commit.GetCommitByPath(filepath.Join(treePath, te.Name()))
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					ctx.Handle(500, "GetCommitOfRelPath", err)
 | 
										ctx.Handle(500, "GetCommitByPath", err)
 | 
				
			||||||
					return
 | 
										return
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				files = append(files, []interface{}{te, c})
 | 
									files = append(files, []interface{}{te, c})
 | 
				
			||||||
@@ -153,9 +154,9 @@ func Home(ctx *middleware.Context) {
 | 
				
			|||||||
					smUrl = sm.Url
 | 
										smUrl = sm.Url
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				c, err := ctx.Repo.Commit.GetCommitOfRelPath(filepath.Join(treePath, te.Name()))
 | 
									c, err := ctx.Repo.Commit.GetCommitByPath(filepath.Join(treePath, te.Name()))
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					ctx.Handle(500, "GetCommitOfRelPath", err)
 | 
										ctx.Handle(500, "GetCommitByPath", err)
 | 
				
			||||||
					return
 | 
										return
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				files = append(files, []interface{}{te, git.NewSubModuleFile(c, smUrl, te.ID.String())})
 | 
									files = append(files, []interface{}{te, git.NewSubModuleFile(c, smUrl, te.ID.String())})
 | 
				
			||||||
@@ -209,9 +210,9 @@ func Home(ctx *middleware.Context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		lastCommit := ctx.Repo.Commit
 | 
							lastCommit := ctx.Repo.Commit
 | 
				
			||||||
		if len(treePath) > 0 {
 | 
							if len(treePath) > 0 {
 | 
				
			||||||
			c, err := ctx.Repo.Commit.GetCommitOfRelPath(treePath)
 | 
								c, err := ctx.Repo.Commit.GetCommitByPath(treePath)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				ctx.Handle(500, "GetCommitOfRelPath", err)
 | 
									ctx.Handle(500, "GetCommitByPath", err)
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			lastCommit = c
 | 
								lastCommit = c
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,9 +42,9 @@ func renderWikiPage(ctx *middleware.Context, isViewPage bool) (*git.Repository,
 | 
				
			|||||||
		ctx.Handle(500, "OpenRepository", err)
 | 
							ctx.Handle(500, "OpenRepository", err)
 | 
				
			||||||
		return nil, ""
 | 
							return nil, ""
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	commit, err := wikiRepo.GetCommitOfBranch("master")
 | 
						commit, err := wikiRepo.GetBranchCommit("master")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Handle(500, "GetCommitOfBranch", err)
 | 
							ctx.Handle(500, "GetBranchCommit", err)
 | 
				
			||||||
		return nil, ""
 | 
							return nil, ""
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -147,9 +147,9 @@ func WikiPages(ctx *middleware.Context) {
 | 
				
			|||||||
		ctx.Handle(500, "OpenRepository", err)
 | 
							ctx.Handle(500, "OpenRepository", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	commit, err := wikiRepo.GetCommitOfBranch("master")
 | 
						commit, err := wikiRepo.GetBranchCommit("master")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Handle(500, "GetCommitOfBranch", err)
 | 
							ctx.Handle(500, "GetBranchCommit", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +1 @@
 | 
				
			|||||||
0.7.36.1209 Beta
 | 
					0.7.37.1209 Beta
 | 
				
			||||||
		Reference in New Issue
	
	Block a user