* update git vendor to fix wrong release commit id and add migrations * fix count * fix migration release * fix teststags/v1.9.0-dev
| @@ -3,11 +3,11 @@ | |||||
| [[projects]] | [[projects]] | ||||
| branch = "master" | branch = "master" | ||||
| digest = "1:0a001725d6e1b35faccf15cbc4f782b67a0d77f4bbf56e51a4b244f92e7c60ca" | |||||
| digest = "1:0f0ada42a7b1bd64794bf8fea917c2cd626d6b0539173e3704cd764b93eb5312" | |||||
| name = "code.gitea.io/git" | name = "code.gitea.io/git" | ||||
| packages = ["."] | packages = ["."] | ||||
| pruneopts = "NUT" | pruneopts = "NUT" | ||||
| revision = "0aea7f12d36ed49bcac560b61301cff88e478e5c" | |||||
| revision = "8983773ac6fef49203e7ee8cdbfde3e118bc3421" | |||||
| [[projects]] | [[projects]] | ||||
| branch = "master" | branch = "master" | ||||
| @@ -217,6 +217,8 @@ var migrations = []Migration{ | |||||
| NewMigration("add is locked to issues", addIsLockedToIssues), | NewMigration("add is locked to issues", addIsLockedToIssues), | ||||
| // v81 -> v82 | // v81 -> v82 | ||||
| NewMigration("update U2F counter type", changeU2FCounterType), | NewMigration("update U2F counter type", changeU2FCounterType), | ||||
| // v82 -> v83 | |||||
| NewMigration("hot fix for wrong release sha1 on release table", fixReleaseSha1OnReleaseTable), | |||||
| } | } | ||||
| // Migrate database to current version | // Migrate database to current version | ||||
| @@ -0,0 +1,87 @@ | |||||
| // Copyright 2019 The Gitea 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 migrations | |||||
| import ( | |||||
| "code.gitea.io/git" | |||||
| "code.gitea.io/gitea/models" | |||||
| "github.com/go-xorm/xorm" | |||||
| ) | |||||
| func fixReleaseSha1OnReleaseTable(x *xorm.Engine) error { | |||||
| type Release struct { | |||||
| ID int64 | |||||
| RepoID int64 | |||||
| Sha1 string | |||||
| TagName string | |||||
| } | |||||
| // Update release sha1 | |||||
| const batchSize = 100 | |||||
| sess := x.NewSession() | |||||
| defer sess.Close() | |||||
| var ( | |||||
| err error | |||||
| count int | |||||
| gitRepoCache = make(map[int64]*git.Repository) | |||||
| repoCache = make(map[int64]*models.Repository) | |||||
| ) | |||||
| if err = sess.Begin(); err != nil { | |||||
| return err | |||||
| } | |||||
| for start := 0; ; start += batchSize { | |||||
| releases := make([]*Release, 0, batchSize) | |||||
| if err = sess.Limit(batchSize, start).Asc("id").Where("is_tag=?", false).Find(&releases); err != nil { | |||||
| return err | |||||
| } | |||||
| if len(releases) == 0 { | |||||
| break | |||||
| } | |||||
| for _, release := range releases { | |||||
| gitRepo, ok := gitRepoCache[release.RepoID] | |||||
| if !ok { | |||||
| repo, ok := repoCache[release.RepoID] | |||||
| if !ok { | |||||
| repo, err = models.GetRepositoryByID(release.RepoID) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| repoCache[release.RepoID] = repo | |||||
| } | |||||
| gitRepo, err = git.OpenRepository(repo.RepoPath()) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| gitRepoCache[release.RepoID] = gitRepo | |||||
| } | |||||
| release.Sha1, err = gitRepo.GetTagCommitID(release.TagName) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| if _, err = sess.ID(release.ID).Cols("sha1").Update(release); err != nil { | |||||
| return err | |||||
| } | |||||
| count++ | |||||
| if count >= 1000 { | |||||
| if err = sess.Commit(); err != nil { | |||||
| return err | |||||
| } | |||||
| if err = sess.Begin(); err != nil { | |||||
| return err | |||||
| } | |||||
| count = 0 | |||||
| } | |||||
| } | |||||
| } | |||||
| return sess.Commit() | |||||
| } | |||||
| @@ -110,10 +110,6 @@ func (repo *Repository) CheckBranchName(name string) error { | |||||
| return err | return err | ||||
| } | } | ||||
| if _, err := gitRepo.GetTag(name); err == nil { | |||||
| return ErrTagAlreadyExists{name} | |||||
| } | |||||
| branches, err := repo.GetBranches() | branches, err := repo.GetBranches() | ||||
| if err != nil { | if err != nil { | ||||
| return err | return err | ||||
| @@ -127,6 +123,11 @@ func (repo *Repository) CheckBranchName(name string) error { | |||||
| return ErrBranchNameConflict{branch.Name} | return ErrBranchNameConflict{branch.Name} | ||||
| } | } | ||||
| } | } | ||||
| if _, err := gitRepo.GetTag(name); err == nil { | |||||
| return ErrTagAlreadyExists{name} | |||||
| } | |||||
| return nil | return nil | ||||
| } | } | ||||
| @@ -49,7 +49,7 @@ func renderDirectory(ctx *context.Context, treeLink string) { | |||||
| } | } | ||||
| entries.CustomSort(base.NaturalSortLess) | entries.CustomSort(base.NaturalSortLess) | ||||
| ctx.Data["Files"], err = entries.GetCommitsInfo(ctx.Repo.Commit, ctx.Repo.TreePath) | |||||
| ctx.Data["Files"], err = entries.GetCommitsInfo(ctx.Repo.Commit, ctx.Repo.TreePath, nil) | |||||
| if err != nil { | if err != nil { | ||||
| ctx.ServerError("GetCommitsInfo", err) | ctx.ServerError("GetCommitsInfo", err) | ||||
| return | return | ||||
| @@ -0,0 +1,11 @@ | |||||
| // Copyright 2019 The Gitea 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 | |||||
| // LastCommitCache cache | |||||
| type LastCommitCache interface { | |||||
| Get(repoPath, ref, entryPath string) (*Commit, error) | |||||
| Put(repoPath, ref, entryPath string, commit *Commit) error | |||||
| } | |||||
| @@ -72,13 +72,20 @@ func (state *getCommitsInfoState) getTargetedEntryPath() string { | |||||
| } | } | ||||
| // repeatedly perform targeted searches for unpopulated entries | // repeatedly perform targeted searches for unpopulated entries | ||||
| func targetedSearch(state *getCommitsInfoState, done chan error) { | |||||
| func targetedSearch(state *getCommitsInfoState, done chan error, cache LastCommitCache) { | |||||
| for { | for { | ||||
| entryPath := state.getTargetedEntryPath() | entryPath := state.getTargetedEntryPath() | ||||
| if len(entryPath) == 0 { | if len(entryPath) == 0 { | ||||
| done <- nil | done <- nil | ||||
| return | return | ||||
| } | } | ||||
| if cache != nil { | |||||
| commit, err := cache.Get(state.headCommit.repo.Path, state.headCommit.ID.String(), entryPath) | |||||
| if err == nil && commit != nil { | |||||
| state.update(entryPath, commit) | |||||
| continue | |||||
| } | |||||
| } | |||||
| command := NewCommand("rev-list", "-1", state.headCommit.ID.String(), "--", entryPath) | command := NewCommand("rev-list", "-1", state.headCommit.ID.String(), "--", entryPath) | ||||
| output, err := command.RunInDir(state.headCommit.repo.Path) | output, err := command.RunInDir(state.headCommit.repo.Path) | ||||
| if err != nil { | if err != nil { | ||||
| @@ -96,6 +103,9 @@ func targetedSearch(state *getCommitsInfoState, done chan error) { | |||||
| return | return | ||||
| } | } | ||||
| state.update(entryPath, commit) | state.update(entryPath, commit) | ||||
| if cache != nil { | |||||
| cache.Put(state.headCommit.repo.Path, state.headCommit.ID.String(), entryPath, commit) | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -118,9 +128,9 @@ func initGetCommitInfoState(entries Entries, headCommit *Commit, treePath string | |||||
| } | } | ||||
| // GetCommitsInfo gets information of all commits that are corresponding to these entries | // GetCommitsInfo gets information of all commits that are corresponding to these entries | ||||
| func (tes Entries) GetCommitsInfo(commit *Commit, treePath string) ([][]interface{}, error) { | |||||
| func (tes Entries) GetCommitsInfo(commit *Commit, treePath string, cache LastCommitCache) ([][]interface{}, error) { | |||||
| state := initGetCommitInfoState(tes, commit, treePath) | state := initGetCommitInfoState(tes, commit, treePath) | ||||
| if err := getCommitsInfo(state); err != nil { | |||||
| if err := getCommitsInfo(state, cache); err != nil { | |||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| if len(state.commits) < len(state.entryPaths) { | if len(state.commits) < len(state.entryPaths) { | ||||
| @@ -188,7 +198,7 @@ func (state *getCommitsInfoState) update(entryPath string, commit *Commit) bool | |||||
| const getCommitsInfoPretty = "--pretty=format:%H %ct %s" | const getCommitsInfoPretty = "--pretty=format:%H %ct %s" | ||||
| func getCommitsInfo(state *getCommitsInfoState) error { | |||||
| func getCommitsInfo(state *getCommitsInfoState, cache LastCommitCache) error { | |||||
| ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) | ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) | ||||
| defer cancel() | defer cancel() | ||||
| @@ -215,7 +225,7 @@ func getCommitsInfo(state *getCommitsInfoState) error { | |||||
| numThreads := runtime.NumCPU() | numThreads := runtime.NumCPU() | ||||
| done := make(chan error, numThreads) | done := make(chan error, numThreads) | ||||
| for i := 0; i < numThreads; i++ { | for i := 0; i < numThreads; i++ { | ||||
| go targetedSearch(state, done) | |||||
| go targetedSearch(state, done, cache) | |||||
| } | } | ||||
| scanner := bufio.NewScanner(readCloser) | scanner := bufio.NewScanner(readCloser) | ||||
| @@ -32,7 +32,14 @@ func (repo *Repository) GetBranchCommitID(name string) (string, error) { | |||||
| // GetTagCommitID returns last commit ID string of given tag. | // GetTagCommitID returns last commit ID string of given tag. | ||||
| func (repo *Repository) GetTagCommitID(name string) (string, error) { | func (repo *Repository) GetTagCommitID(name string) (string, error) { | ||||
| return repo.GetRefCommitID(TagPrefix + name) | |||||
| stdout, err := NewCommand("rev-list", "-n", "1", name).RunInDir(repo.Path) | |||||
| if err != nil { | |||||
| if strings.Contains(err.Error(), "unknown revision or path") { | |||||
| return "", ErrNotExist{name, ""} | |||||
| } | |||||
| return "", err | |||||
| } | |||||
| return strings.TrimSpace(stdout), nil | |||||
| } | } | ||||
| // parseCommitData parses commit information from the (uncompressed) raw | // parseCommitData parses commit information from the (uncompressed) raw | ||||
| @@ -76,12 +76,12 @@ func (repo *Repository) getTag(id SHA1) (*Tag, error) { | |||||
| // GetTag returns a Git tag by given name. | // GetTag returns a Git tag by given name. | ||||
| func (repo *Repository) GetTag(name string) (*Tag, error) { | func (repo *Repository) GetTag(name string) (*Tag, error) { | ||||
| stdout, err := NewCommand("show-ref", "--tags", name).RunInDir(repo.Path) | |||||
| idStr, err := repo.GetTagCommitID(name) | |||||
| if err != nil { | if err != nil { | ||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| id, err := NewIDFromString(strings.Split(stdout, " ")[0]) | |||||
| id, err := NewIDFromString(idStr) | |||||
| if err != nil { | if err != nil { | ||||
| return nil, err | return nil, err | ||||
| } | } | ||||