| @@ -20,6 +20,7 @@ github.com/gogits/chardet = commit:2404f77725 | |||||
| github.com/gogits/git-shell = | github.com/gogits/git-shell = | ||||
| github.com/gogits/go-gogs-client = commit:4b541fa | github.com/gogits/go-gogs-client = commit:4b541fa | ||||
| github.com/issue9/identicon = commit:f8c0d2c | github.com/issue9/identicon = commit:f8c0d2c | ||||
| github.com/kardianos/minwinsvc = | |||||
| github.com/klauspost/compress = commit:bcd0709 | github.com/klauspost/compress = commit:bcd0709 | ||||
| github.com/klauspost/cpuid = commit:8d9fe96 | github.com/klauspost/cpuid = commit:8d9fe96 | ||||
| github.com/klauspost/crc32 = commit:0aff1ea | github.com/klauspost/crc32 = commit:0aff1ea | ||||
| @@ -5,7 +5,7 @@ Gogs - Go Git Service [ |  | ||||
| ##### Current version: 0.7.36 Beta | |||||
| ##### Current version: 0.7.37 Beta | |||||
| | Web | UI | Preview | | | Web | UI | Preview | | ||||
| |:-------------:|:-------:|:-------:| | |:-------------:|:-------:|:-------:| | ||||
| @@ -29,6 +29,8 @@ import ( | |||||
| "gopkg.in/ini.v1" | "gopkg.in/ini.v1" | ||||
| "gopkg.in/macaron.v1" | "gopkg.in/macaron.v1" | ||||
| "github.com/gogits/git-shell" | |||||
| "github.com/gogits/gogs/models" | "github.com/gogits/gogs/models" | ||||
| "github.com/gogits/gogs/modules/auth" | "github.com/gogits/gogs/modules/auth" | ||||
| "github.com/gogits/gogs/modules/avatar" | "github.com/gogits/gogs/modules/avatar" | ||||
| @@ -78,7 +80,6 @@ func checkVersion() { | |||||
| // Check dependency version. | // Check dependency version. | ||||
| checkers := []VerChecker{ | checkers := []VerChecker{ | ||||
| {"github.com/go-xorm/xorm", func() string { return xorm.Version }, "0.4.4.1029"}, | {"github.com/go-xorm/xorm", func() string { return xorm.Version }, "0.4.4.1029"}, | ||||
| {"github.com/Unknwon/macaron", macaron.Version, "0.5.4"}, | |||||
| {"github.com/go-macaron/binding", binding.Version, "0.1.0"}, | {"github.com/go-macaron/binding", binding.Version, "0.1.0"}, | ||||
| {"github.com/go-macaron/cache", cache.Version, "0.1.2"}, | {"github.com/go-macaron/cache", cache.Version, "0.1.2"}, | ||||
| {"github.com/go-macaron/csrf", csrf.Version, "0.0.3"}, | {"github.com/go-macaron/csrf", csrf.Version, "0.0.3"}, | ||||
| @@ -86,10 +87,12 @@ 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, ">=") { | ||||
| log.Fatal(4, "Package '%s' version is too old(%s -> %s), did you forget to update?", c.ImportPath, c.Version(), c.Expected) | |||||
| log.Fatal(4, "Package '%s' version is too old (%s -> %s), did you forget to update?", c.ImportPath, c.Version(), c.Expected) | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -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 | |||||
| NumCommitsBehind int `xorm:"-"` | |||||
| NumCommits int64 | |||||
| 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. | |||||
| 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, | |||||
| }) | |||||
| } | |||||
| if err = CommitRepoAction(userID, user.Id, userName, actEmail, | |||||
| repo.ID, repoUserName, repoName, refName, &PushCommits{l.Len(), commits, "", nil}, oldCommitID, newCommitID); err != nil { | |||||
| if err = CommitRepoAction(userID, user.Id, userName, user.Email, | |||||
| repo.ID, repoUserName, repoName, refName, ListToPushCommits(l), 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" | ||||
| ) | ) | ||||
| @@ -21,7 +22,7 @@ func ServeData(ctx *middleware.Context, name string, reader io.Reader) error { | |||||
| } | } | ||||
| _, isTextFile := base.IsTextFile(buf) | _, isTextFile := base.IsTextFile(buf) | ||||
| if ! isTextFile { | |||||
| if !isTextFile { | |||||
| _, isImageFile := base.IsImageFile(buf) | _, isImageFile := base.IsImageFile(buf) | ||||
| if !isImageFile { | if !isImageFile { | ||||
| ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+path.Base(ctx.Repo.TreeName)) | ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+path.Base(ctx.Repo.TreeName)) | ||||
| @@ -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 { | |||||
| c, err := ctx.Repo.Commit.GetCommitOfRelPath(filepath.Join(treePath, te.Name())) | |||||
| if te.Type != git.OBJECT_COMMIT { | |||||
| 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 | |||||