Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync releases table with tags on push and for mirrors #2459

Merged
merged 7 commits into from
Sep 20, 2017
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions models/migrations/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ var migrations = []Migration{
NewMigration("migrate protected branch struct", migrateProtectedBranchStruct),
// v41 -> v42
NewMigration("add default value to user prohibit_login", addDefaultValueToUserProhibitLogin),
// v42 -> v43
NewMigration("add tags to releases and sync existing repositories", releaseAddColumnIsTagAndSyncTags),
}

// Migrate database to current version
Expand Down
57 changes: 57 additions & 0 deletions models/migrations/v42.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2017 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 (
"fmt"

"code.gitea.io/git"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/log"

"github.com/go-xorm/xorm"
)

// ReleaseV39 describes the added field for Release
type ReleaseV39 struct {
IsTag bool `xorm:"NOT NULL DEFAULT false"`
}

// TableName will be invoked by XORM to customrize the table name
func (*ReleaseV39) TableName() string {
return "release"
}

func releaseAddColumnIsTagAndSyncTags(x *xorm.Engine) error {
if err := x.Sync2(new(ReleaseV39)); err != nil {
return fmt.Errorf("Sync2: %v", err)
}

// For the sake of SQLite3, we can't use x.Iterate here.
offset := 0
pageSize := 20
for {
repos := make([]*models.Repository, 0, pageSize)
if err := x.Table("repository").Asc("id").Limit(pageSize, offset).Find(&repos); err != nil {
return fmt.Errorf("select repos [offset: %d]: %v", offset, err)
}
for _, repo := range repos {
gitRepo, err := git.OpenRepository(repo.RepoPath())
if err != nil {
log.Warn("OpenRepository: %v", err)
continue
}

if err = models.SyncReleasesWithTags(repo, gitRepo); err != nil {
log.Warn("SyncReleasesWithTags: %v", err)
}
}
if len(repos) < pageSize {
break
}
offset += pageSize
}
return nil
}
86 changes: 72 additions & 14 deletions models/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ type Release struct {
NumCommitsBehind int64 `xorm:"-"`
Note string `xorm:"TEXT"`
IsDraft bool `xorm:"NOT NULL DEFAULT false"`
IsPrerelease bool
IsPrerelease bool `xorm:"NOT NULL DEFAULT false"`
IsTag bool `xorm:"NOT NULL DEFAULT false"`

Attachments []*Attachment `xorm:"-"`

Expand Down Expand Up @@ -139,17 +140,17 @@ func createTag(gitRepo *git.Repository, rel *Release) error {
}
return err
}
} else {
commit, err := gitRepo.GetTagCommit(rel.TagName)
if err != nil {
return fmt.Errorf("GetTagCommit: %v", err)
}
}
commit, err := gitRepo.GetTagCommit(rel.TagName)
if err != nil {
return fmt.Errorf("GetTagCommit: %v", err)
}

rel.Sha1 = commit.ID.String()
rel.NumCommits, err = commit.CommitsCount()
if err != nil {
return fmt.Errorf("CommitsCount: %v", err)
}
rel.Sha1 = commit.ID.String()
rel.CreatedUnix = commit.Author.When.Unix()
rel.NumCommits, err = commit.CommitsCount()
if err != nil {
return fmt.Errorf("CommitsCount: %v", err)
}
}
return nil
Expand Down Expand Up @@ -236,6 +237,7 @@ func GetReleaseByID(id int64) (*Release, error) {
// FindReleasesOptions describes the conditions to Find releases
type FindReleasesOptions struct {
IncludeDrafts bool
IncludeTags bool
TagNames []string
}

Expand All @@ -246,6 +248,9 @@ func (opts *FindReleasesOptions) toConds(repoID int64) builder.Cond {
if !opts.IncludeDrafts {
cond = cond.And(builder.Eq{"is_draft": false})
}
if !opts.IncludeTags {
cond = cond.And(builder.Eq{"is_tag": false})
}
if len(opts.TagNames) > 0 {
cond = cond.And(builder.In("tag_name", opts.TagNames))
}
Expand Down Expand Up @@ -361,6 +366,8 @@ func UpdateRelease(gitRepo *git.Repository, rel *Release, attachmentUUIDs []stri
if err = createTag(gitRepo, rel); err != nil {
return err
}
rel.LowerTagName = strings.ToLower(rel.TagName)

_, err = x.Id(rel.ID).AllCols().Update(rel)
if err != nil {
return err
Expand Down Expand Up @@ -397,11 +404,62 @@ func DeleteReleaseByID(id int64, u *User, delTag bool) error {
if err != nil && !strings.Contains(stderr, "not found") {
return fmt.Errorf("git tag -d: %v - %s", err, stderr)
}
}

if _, err = x.Id(rel.ID).Delete(new(Release)); err != nil {
return fmt.Errorf("Delete: %v", err)
if _, err = x.Id(rel.ID).Delete(new(Release)); err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update after delete?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

forgot to remove update, good catch, thx

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually it is just in diff looks like this, if you look at the full file code there is no update before delete, update is from other function :)

return fmt.Errorf("Delete: %v", err)
}
} else {
rel.IsTag = true
rel.IsDraft = false
rel.IsPrerelease = false
rel.Title = ""
rel.Note = ""

if _, err = x.Id(rel.ID).AllCols().Update(rel); err != nil {
return fmt.Errorf("Update: %v", err)
}
}

return nil
}

// SyncReleasesWithTags synchronizes release table with repository tags
func SyncReleasesWithTags(repo *Repository, gitRepo *git.Repository) error {
existingRelTags := make(map[string]struct{})
opts := FindReleasesOptions{IncludeDrafts: true, IncludeTags: true}
page := 0
for {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: for page := 1; ; page++ {

page++
rels, err := GetReleasesByRepoID(repo.ID, opts, page, 100)
if err != nil {
return fmt.Errorf("GetReleasesByRepoID: %v", err)
}
if len(rels) == 0 {
break
}
for _, rel := range rels {
if rel.IsDraft {
continue
}
if !gitRepo.IsTagExist(rel.TagName) {
if err := pushUpdateDeleteTag(repo, gitRepo, rel.TagName); err != nil {
return fmt.Errorf("pushUpdateDeleteTag: %v", err)
}
} else {
existingRelTags[strings.ToLower(rel.TagName)] = struct{}{}
}
}
}
tags, err := gitRepo.GetTags()
if err != nil {
return fmt.Errorf("GetTags: %v", err)
}
for _, tagName := range tags {
if _, ok := existingRelTags[strings.ToLower(tagName)]; !ok {
if err := pushUpdateAddTag(repo, gitRepo, tagName); err != nil {
return fmt.Errorf("pushUpdateAddTag: %v", err)
}
}
}
return nil
}
4 changes: 4 additions & 0 deletions models/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,10 @@ func MigrateRepository(doer, u *User, opts MigrateRepoOptions) (*Repository, err
if headBranch != nil {
repo.DefaultBranch = headBranch.Name
}

if err = SyncReleasesWithTags(repo, gitRepo); err != nil {
log.Error(4, "Failed to synchronize tags to releases for repository: %v", err)
}
}

if err = repo.UpdateSize(); err != nil {
Expand Down
10 changes: 10 additions & 0 deletions models/repo_mirror.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/go-xorm/xorm"
"gopkg.in/ini.v1"

"code.gitea.io/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/setting"
Expand Down Expand Up @@ -156,6 +157,15 @@ func (m *Mirror) runSync() bool {
return false
}

gitRepo, err := git.OpenRepository(repoPath)
if err != nil {
log.Error(4, "OpenRepository: %v", err)
return false
}
if err = SyncReleasesWithTags(m.Repo, gitRepo); err != nil {
log.Error(4, "Failed to synchronize tags to releases for repository: %v", err)
}

if err := m.Repo.UpdateSize(); err != nil {
log.Error(4, "Failed to update size for mirror repository: %v", err)
}
Expand Down
103 changes: 98 additions & 5 deletions models/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,91 @@ func PushUpdate(branch string, opt PushUpdateOptions) error {
return nil
}

func pushUpdateDeleteTag(repo *Repository, gitRepo *git.Repository, tagName string) error {
rel, err := GetRelease(repo.ID, tagName)
if err != nil {
if IsErrReleaseNotExist(err) {
return nil
}
return fmt.Errorf("GetRelease: %v", err)
}
if rel.IsTag {
if _, err = x.Id(rel.ID).Delete(new(Release)); err != nil {
return fmt.Errorf("Delete: %v", err)
}
} else {
rel.IsDraft = true
rel.NumCommits = 0
rel.Sha1 = ""
if _, err = x.Id(rel.ID).AllCols().Update(rel); err != nil {
return fmt.Errorf("Update: %v", err)
}
}

return nil
}

func pushUpdateAddTag(repo *Repository, gitRepo *git.Repository, tagName string) error {
rel, err := GetRelease(repo.ID, tagName)
if err != nil && !IsErrReleaseNotExist(err) {
return fmt.Errorf("GetRelease: %v", err)
}

tag, err := gitRepo.GetTag(tagName)
if err != nil {
return fmt.Errorf("GetTag: %v", err)
}
commit, err := tag.Commit()
if err != nil {
return fmt.Errorf("Commit: %v", err)
}
tagCreatedUnix := commit.Author.When.Unix()

author, err := GetUserByEmail(commit.Author.Email)
if err != nil && !IsErrUserNotExist(err) {
return fmt.Errorf("GetUserByEmail: %v", err)
}

commitsCount, err := commit.CommitsCount()
if err != nil {
return fmt.Errorf("CommitsCount: %v", err)
}

if rel == nil {
rel = &Release{
RepoID: repo.ID,
Title: "",
TagName: tagName,
Target: "",
Sha1: commit.ID.String(),
NumCommits: commitsCount,
Note: "",
IsDraft: false,
IsPrerelease: false,
IsTag: true,
CreatedUnix: tagCreatedUnix,
}
if author != nil {
rel.PublisherID = author.ID
}

if _, err = x.InsertOne(rel); err != nil {
return fmt.Errorf("InsertOne: %v", err)
}
} else {
rel.Sha1 = commit.ID.String()
rel.CreatedUnix = tagCreatedUnix
rel.NumCommits = commitsCount
if rel.IsTag && author != nil {
rel.PublisherID = author.ID
}
if _, err = x.Id(rel.ID).AllCols().Update(rel); err != nil {
return fmt.Errorf("Update: %v", err)
}
}
return nil
}

func pushUpdate(opts PushUpdateOptions) (repo *Repository, err error) {
isNewRef := opts.OldCommitID == git.EmptySHA
isDelRef := opts.NewCommitID == git.EmptySHA
Expand All @@ -106,23 +191,31 @@ func pushUpdate(opts PushUpdateOptions) (repo *Repository, err error) {
return nil, fmt.Errorf("GetRepositoryByName: %v", err)
}

gitRepo, err := git.OpenRepository(repoPath)
if err != nil {
return nil, fmt.Errorf("OpenRepository: %v", err)
}

if isDelRef {
// Tag has been deleted
if strings.HasPrefix(opts.RefFullName, git.TagPrefix) {
err = pushUpdateDeleteTag(repo, gitRepo, opts.RefFullName[len(git.TagPrefix):])
if err != nil {
return nil, fmt.Errorf("pushUpdateDeleteTag: %v", err)
}
}
log.GitLogger.Info("Reference '%s' has been deleted from '%s/%s' by %s",
opts.RefFullName, opts.RepoUserName, opts.RepoName, opts.PusherName)
return repo, nil
}

gitRepo, err := git.OpenRepository(repoPath)
if err != nil {
return nil, fmt.Errorf("OpenRepository: %v", err)
}

if err = repo.UpdateSize(); err != nil {
log.Error(4, "Failed to update size for repository: %v", err)
}

// Push tags.
if strings.HasPrefix(opts.RefFullName, git.TagPrefix) {
pushUpdateAddTag(repo, gitRepo, opts.RefFullName[len(git.TagPrefix):])
if err := CommitRepoAction(CommitRepoActionOptions{
PusherName: opts.PusherName,
RepoOwnerID: owner.ID,
Expand Down
1 change: 1 addition & 0 deletions modules/context/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ func RepoAssignment() macaron.Handler {

count, err := models.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, models.FindReleasesOptions{
IncludeDrafts: false,
IncludeTags: true,
})
if err != nil {
ctx.Handle(500, "GetReleaseCountByRepoID", err)
Expand Down
Loading