move out git module and #1573 send push hook
This commit is contained in:
parent
bd5dc626e8
commit
9a2e43bff2
45 changed files with 185 additions and 2002 deletions
|
@ -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 [![Build Status](https://travis-ci.org/gogits/gogs.svg?bra
|
||||||
|
|
||||||
![](public/img/gogs-large-resize.png)
|
![](public/img/gogs-large-resize.png)
|
||||||
|
|
||||||
##### 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
|
Loading…
Reference in a new issue