* make releases faster than before and resolved #490 * fix comment
This commit is contained in:
		
							parent
							
								
									79d527195d
								
							
						
					
					
						commit
						61306fa737
					
				| @ -22,12 +22,12 @@ import ( | ||||
| 
 | ||||
| // Release represents a release of repository.
 | ||||
| type Release struct { | ||||
| 	ID               int64 `xorm:"pk autoincr"` | ||||
| 	RepoID           int64 | ||||
| 	ID               int64       `xorm:"pk autoincr"` | ||||
| 	RepoID           int64       `xorm:"index unique(n)"` | ||||
| 	Repo             *Repository `xorm:"-"` | ||||
| 	PublisherID      int64 | ||||
| 	Publisher        *User `xorm:"-"` | ||||
| 	TagName          string | ||||
| 	Publisher        *User  `xorm:"-"` | ||||
| 	TagName          string `xorm:"index unique(n)"` | ||||
| 	LowerTagName     string | ||||
| 	Target           string | ||||
| 	Title            string | ||||
| @ -213,6 +213,15 @@ func GetReleasesByRepoID(repoID int64, page, pageSize int) (rels []*Release, err | ||||
| 	return rels, err | ||||
| } | ||||
| 
 | ||||
| // GetReleasesByRepoIDAndNames returns a list of releases of repository accroding repoID and tagNames.
 | ||||
| func GetReleasesByRepoIDAndNames(repoID int64, tagNames []string) (rels []*Release, err error) { | ||||
| 	err = x. | ||||
| 		Desc("created_unix"). | ||||
| 		In("tag_name", tagNames). | ||||
| 		Find(&rels, Release{RepoID: repoID}) | ||||
| 	return rels, err | ||||
| } | ||||
| 
 | ||||
| type releaseSorter struct { | ||||
| 	rels []*Release | ||||
| } | ||||
|  | ||||
| @ -5,8 +5,10 @@ | ||||
| package repo | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"code.gitea.io/git" | ||||
| 	"code.gitea.io/gitea/models" | ||||
| 	"code.gitea.io/gitea/modules/auth" | ||||
| 	"code.gitea.io/gitea/modules/base" | ||||
| @ -54,34 +56,55 @@ func Releases(ctx *context.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("repo.release.releases") | ||||
| 	ctx.Data["PageIsReleaseList"] = true | ||||
| 
 | ||||
| 	rawTags, err := ctx.Repo.GitRepo.GetTags() | ||||
| 	page := ctx.QueryInt("page") | ||||
| 	if page <= 1 { | ||||
| 		page = 1 | ||||
| 	} | ||||
| 	limit := ctx.QueryInt("limit") | ||||
| 	if limit <= 0 { | ||||
| 		limit = 10 | ||||
| 	} | ||||
| 
 | ||||
| 	rawTags, err := ctx.Repo.GitRepo.GetTagInfos(git.TagOption{}) | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(500, "GetTags", err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	page := ctx.QueryInt("page") | ||||
| 	if page <= 1 { | ||||
| 		page = 1 | ||||
| 	if len(rawTags) <= (page-1)*limit { | ||||
| 		ctx.Handle(500, "Releases", errors.New("no more pages")) | ||||
| 		return | ||||
| 	} | ||||
| 	releases, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID, page, 10) | ||||
| 
 | ||||
| 	var tags []*git.Tag | ||||
| 	if page*limit > len(rawTags) { | ||||
| 		tags = rawTags[(page-1)*limit:] | ||||
| 	} else { | ||||
| 		tags = rawTags[(page-1)*limit : page*limit] | ||||
| 	} | ||||
| 
 | ||||
| 	var tagNames []string | ||||
| 	for _, t := range tags { | ||||
| 		tagNames = append(tagNames, t.Name) | ||||
| 	} | ||||
| 
 | ||||
| 	releases, err := models.GetReleasesByRepoIDAndNames(ctx.Repo.Repository.ID, tagNames) | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(500, "GetReleasesByRepoID", err) | ||||
| 		ctx.Handle(500, "GetReleasesByRepoIDAndNames", err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// Temproray cache commits count of used branches to speed up.
 | ||||
| 	countCache := make(map[string]int64) | ||||
| 
 | ||||
| 	var cacheUsers = make(map[int64]*models.User) | ||||
| 	var ok bool | ||||
| 	tags := make([]*models.Release, len(rawTags)) | ||||
| 	for i, rawTag := range rawTags { | ||||
| 		for j, r := range releases { | ||||
| 			if r == nil || (r.IsDraft && !ctx.Repo.IsOwner()) { | ||||
| 	releaseTags := make([]*models.Release, len(tags)) | ||||
| 	for i, rawTag := range tags { | ||||
| 		for _, r := range releases { | ||||
| 			if r.IsDraft && !ctx.Repo.IsOwner() { | ||||
| 				continue | ||||
| 			} | ||||
| 			if r.TagName == rawTag { | ||||
| 			if r.TagName == rawTag.Name { | ||||
| 				if r.Publisher, ok = cacheUsers[r.PublisherID]; !ok { | ||||
| 					r.Publisher, err = models.GetUserByID(r.PublisherID) | ||||
| 					if err != nil { | ||||
| @ -101,64 +124,31 @@ func Releases(ctx *context.Context) { | ||||
| 				} | ||||
| 
 | ||||
| 				r.Note = markdown.RenderString(r.Note, ctx.Repo.RepoLink, ctx.Repo.Repository.ComposeMetas()) | ||||
| 				tags[i] = r | ||||
| 				releases[j] = nil // Mark as used.
 | ||||
| 				releaseTags[i] = r | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if tags[i] == nil { | ||||
| 			commit, err := ctx.Repo.GitRepo.GetTagCommit(rawTag) | ||||
| 			if err != nil { | ||||
| 				ctx.Handle(500, "GetTagCommit", err) | ||||
| 				return | ||||
| 		if releaseTags[i] == nil { | ||||
| 			releaseTags[i] = &models.Release{ | ||||
| 				Title:   rawTag.Name, | ||||
| 				TagName: rawTag.Name, | ||||
| 				Sha1:    rawTag.Object.String(), | ||||
| 				Note:    rawTag.Message, | ||||
| 			} | ||||
| 
 | ||||
| 			tags[i] = &models.Release{ | ||||
| 				Title:   rawTag, | ||||
| 				TagName: rawTag, | ||||
| 				Sha1:    commit.ID.String(), | ||||
| 			} | ||||
| 
 | ||||
| 			tags[i].NumCommits, err = commit.CommitsCount() | ||||
| 			releaseTags[i].NumCommits, err = git.CommitsCount(ctx.Repo.GitRepo.Path, rawTag.Object.String()) | ||||
| 			if err != nil { | ||||
| 				ctx.Handle(500, "CommitsCount", err) | ||||
| 				return | ||||
| 			} | ||||
| 			tags[i].NumCommitsBehind = ctx.Repo.CommitsCount - tags[i].NumCommits | ||||
| 			releaseTags[i].NumCommitsBehind = ctx.Repo.CommitsCount - releaseTags[i].NumCommits | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	for _, r := range releases { | ||||
| 		if r == nil { | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		if r.Publisher, ok = cacheUsers[r.PublisherID]; !ok { | ||||
| 			r.Publisher, err = models.GetUserByID(r.PublisherID) | ||||
| 			if err != nil { | ||||
| 				if models.IsErrUserNotExist(err) { | ||||
| 					r.Publisher = models.NewGhostUser() | ||||
| 				} else { | ||||
| 					ctx.Handle(500, "GetUserByID", err) | ||||
| 					return | ||||
| 				} | ||||
| 			} | ||||
| 			cacheUsers[r.PublisherID] = r.Publisher | ||||
| 		} | ||||
| 
 | ||||
| 		if err := calReleaseNumCommitsBehind(ctx.Repo, r, countCache); err != nil { | ||||
| 			ctx.Handle(500, "calReleaseNumCommitsBehind", err) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		r.Note = markdown.RenderString(r.Note, ctx.Repo.RepoLink, ctx.Repo.Repository.ComposeMetas()) | ||||
| 		tags = append(tags, r) | ||||
| 	} | ||||
| 	pager := paginater.New(ctx.Repo.Repository.NumTags, 10, page, 5) | ||||
| 	pager := paginater.New(ctx.Repo.Repository.NumTags, limit, page, 5) | ||||
| 	ctx.Data["Page"] = pager | ||||
| 	models.SortReleases(tags) | ||||
| 	ctx.Data["Releases"] = tags | ||||
| 	ctx.Data["Releases"] = releaseTags | ||||
| 	ctx.HTML(200, tplReleases) | ||||
| } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										1
									
								
								vendor/code.gitea.io/git/MAINTAINERS
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/code.gitea.io/git/MAINTAINERS
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,5 +1,6 @@ | ||||
| Alexey Makhov <amakhov@avito.ru> (@makhov) | ||||
| Andrey Nering <andrey.nering@gmail.com> (@andreynering) | ||||
| Bo-Yi Wu <appleboy.tw@gmail.com> (@appleboy) | ||||
| Kees de Vries <bouwko@gmail.com> (@Bwko) | ||||
| Kim Carlbäcker <kim.carlbacker@gmail.com> (@bkcsoft) | ||||
| LefsFlare <nobody@nobody.tld> (@LefsFlarey) | ||||
|  | ||||
							
								
								
									
										82
									
								
								vendor/code.gitea.io/git/repo_tag.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										82
									
								
								vendor/code.gitea.io/git/repo_tag.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -6,6 +6,7 @@ package git | ||||
| 
 | ||||
| import ( | ||||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/mcuadros/go-version" | ||||
| ) | ||||
| @ -94,6 +95,87 @@ func (repo *Repository) GetTag(name string) (*Tag, error) { | ||||
| 	return tag, nil | ||||
| } | ||||
| 
 | ||||
| // TagOption describes tag options
 | ||||
| type TagOption struct { | ||||
| } | ||||
| 
 | ||||
| // parseTag parse the line
 | ||||
| // 2016-10-14 20:54:25 +0200  (tag: translation/20161014.01) d3b76dcf2 Dirk Baeumer dirkb@microsoft.com Merge in translations
 | ||||
| func parseTag(line string, opt TagOption) (*Tag, error) { | ||||
| 	line = strings.TrimSpace(line) | ||||
| 	if len(line) < 40 { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 
 | ||||
| 	var ( | ||||
| 		err error | ||||
| 		tag Tag | ||||
| 		sig Signature | ||||
| 	) | ||||
| 	sig.When, err = time.Parse("2006-01-02 15:04:05 -0700", line[0:25]) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	left := strings.TrimSpace(line[25:]) | ||||
| 	start := strings.Index(left, "(tag: ") | ||||
| 	if start < 0 { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 	end := strings.IndexByte(left[start+1:], ')') | ||||
| 	if end < 0 { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 	end = end + start + 1 | ||||
| 	part := strings.IndexByte(left[start+6:end], ',') | ||||
| 	if part > 0 { | ||||
| 		tag.Name = strings.TrimSpace(left[start+6 : start+6+part]) | ||||
| 	} else { | ||||
| 		tag.Name = strings.TrimSpace(left[start+6 : end]) | ||||
| 	} | ||||
| 	next := strings.IndexByte(left[end+2:], ' ') | ||||
| 	if next < 0 { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 	tag.Object = MustIDFromString(strings.TrimSpace(left[end+2 : end+2+next])) | ||||
| 	next = end + 2 + next | ||||
| 
 | ||||
| 	emailStart := strings.IndexByte(left[next:], '<') | ||||
| 	sig.Name = strings.TrimSpace(left[next:][:emailStart-1]) | ||||
| 	emailEnd := strings.IndexByte(left[next:], '>') | ||||
| 	sig.Email = strings.TrimSpace(left[next:][emailStart+1 : emailEnd]) | ||||
| 	tag.Tagger = &sig | ||||
| 	tag.Message = strings.TrimSpace(left[next+emailEnd+1:]) | ||||
| 	return &tag, nil | ||||
| } | ||||
| 
 | ||||
| // GetTagInfos returns all tag infos of the repository.
 | ||||
| func (repo *Repository) GetTagInfos(opt TagOption) ([]*Tag, error) { | ||||
| 	cmd := NewCommand("log", "--tags", "--simplify-by-decoration", `--pretty=format:"%ci %d %H %cn<%ce> %s"`) | ||||
| 	stdout, err := cmd.RunInDir(repo.Path) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	tagSlices := strings.Split(stdout, "\n") | ||||
| 	var tags []*Tag | ||||
| 	for _, line := range tagSlices { | ||||
| 		line := strings.Trim(line, `"`) | ||||
| 		tag, err := parseTag(line, opt) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		if tag != nil { | ||||
| 			tag.repo = repo | ||||
| 			tags = append(tags, tag) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	sortTagsByTime(tags) | ||||
| 
 | ||||
| 	return tags, nil | ||||
| } | ||||
| 
 | ||||
| // GetTags returns all tags of the repository.
 | ||||
| func (repo *Repository) GetTags() ([]string, error) { | ||||
| 	cmd := NewCommand("tag", "-l") | ||||
|  | ||||
							
								
								
									
										25
									
								
								vendor/code.gitea.io/git/tag.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								vendor/code.gitea.io/git/tag.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -4,7 +4,10 @@ | ||||
| 
 | ||||
| package git | ||||
| 
 | ||||
| import "bytes" | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"sort" | ||||
| ) | ||||
| 
 | ||||
| // Tag represents a Git tag.
 | ||||
| type Tag struct { | ||||
| @ -64,3 +67,23 @@ l: | ||||
| 	} | ||||
| 	return tag, nil | ||||
| } | ||||
| 
 | ||||
| type tagSorter []*Tag | ||||
| 
 | ||||
| func (ts tagSorter) Len() int { | ||||
| 	return len([]*Tag(ts)) | ||||
| } | ||||
| 
 | ||||
| func (ts tagSorter) Less(i, j int) bool { | ||||
| 	return []*Tag(ts)[i].Tagger.When.After([]*Tag(ts)[j].Tagger.When) | ||||
| } | ||||
| 
 | ||||
| func (ts tagSorter) Swap(i, j int) { | ||||
| 	[]*Tag(ts)[i], []*Tag(ts)[j] = []*Tag(ts)[j], []*Tag(ts)[i] | ||||
| } | ||||
| 
 | ||||
| // sortTagsByTime
 | ||||
| func sortTagsByTime(tags []*Tag) { | ||||
| 	sorter := tagSorter(tags) | ||||
| 	sort.Sort(sorter) | ||||
| } | ||||
|  | ||||
							
								
								
									
										6
									
								
								vendor/vendor.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/vendor.json
									
									
									
									
										vendored
									
									
								
							| @ -3,10 +3,10 @@ | ||||
| 	"ignore": "test", | ||||
| 	"package": [ | ||||
| 		{ | ||||
| 			"checksumSHA1": "mIaKLz6373W+jDLjgE/Yzt/exeo=", | ||||
| 			"checksumSHA1": "zK/6EifSPy/O5Vbx7CMWfnLHExI=", | ||||
| 			"path": "code.gitea.io/git", | ||||
| 			"revision": "3d0fa331865619d2f3a7a0fcf23670a389310954", | ||||
| 			"revisionTime": "2016-12-28T14:57:51Z" | ||||
| 			"revision": "a3ee12b97af51eec1b7aa0525f6a39c97520817d", | ||||
| 			"revisionTime": "2017-01-05T02:48:44Z" | ||||
| 		}, | ||||
| 		{ | ||||
| 			"checksumSHA1": "BKj0haFTDebzdC2nACpoGzp3s8A=", | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user