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

Move and rename UpdateRepository #34136

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
102 changes: 0 additions & 102 deletions modules/repository/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,9 @@ import (
"fmt"
"os"
"path/filepath"
"strings"

activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
"code.gitea.io/gitea/modules/log"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
)

const notRegularFileMode = os.ModeSymlink | os.ModeNamedPipe | os.ModeSocket | os.ModeDevice | os.ModeCharDevice | os.ModeIrregular
Expand Down Expand Up @@ -63,97 +55,3 @@ func UpdateRepoSize(ctx context.Context, repo *repo_model.Repository) error {

return repo_model.UpdateRepoSize(ctx, repo.ID, size, lfsSize)
}

// CheckDaemonExportOK creates/removes git-daemon-export-ok for git-daemon...
func CheckDaemonExportOK(ctx context.Context, repo *repo_model.Repository) error {
if err := repo.LoadOwner(ctx); err != nil {
return err
}

// Create/Remove git-daemon-export-ok for git-daemon...
daemonExportFile := filepath.Join(repo.RepoPath(), `git-daemon-export-ok`)

isExist, err := util.IsExist(daemonExportFile)
if err != nil {
log.Error("Unable to check if %s exists. Error: %v", daemonExportFile, err)
return err
}

isPublic := !repo.IsPrivate && repo.Owner.Visibility == api.VisibleTypePublic
if !isPublic && isExist {
if err = util.Remove(daemonExportFile); err != nil {
log.Error("Failed to remove %s: %v", daemonExportFile, err)
}
} else if isPublic && !isExist {
if f, err := os.Create(daemonExportFile); err != nil {
log.Error("Failed to create %s: %v", daemonExportFile, err)
} else {
f.Close()
}
}

return nil
}

// UpdateRepository updates a repository with db context
func UpdateRepository(ctx context.Context, repo *repo_model.Repository, visibilityChanged bool) (err error) {
repo.LowerName = strings.ToLower(repo.Name)

e := db.GetEngine(ctx)

if _, err = e.ID(repo.ID).AllCols().Update(repo); err != nil {
return fmt.Errorf("update: %w", err)
}

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

if visibilityChanged {
if err = repo.LoadOwner(ctx); err != nil {
return fmt.Errorf("LoadOwner: %w", err)
}
if repo.Owner.IsOrganization() {
// Organization repository need to recalculate access table when visibility is changed.
if err = access_model.RecalculateTeamAccesses(ctx, repo, 0); err != nil {
return fmt.Errorf("recalculateTeamAccesses: %w", err)
}
}

// If repo has become private, we need to set its actions to private.
if repo.IsPrivate {
_, err = e.Where("repo_id = ?", repo.ID).Cols("is_private").Update(&activities_model.Action{
IsPrivate: true,
})
if err != nil {
return err
}

if err = repo_model.ClearRepoStars(ctx, repo.ID); err != nil {
return err
}
}

// Create/Remove git-daemon-export-ok for git-daemon...
if err := CheckDaemonExportOK(ctx, repo); err != nil {
return err
}

forkRepos, err := repo_model.GetRepositoriesByForkID(ctx, repo.ID)
if err != nil {
return fmt.Errorf("getRepositoriesByForkID: %w", err)
}
for i := range forkRepos {
forkRepos[i].IsPrivate = repo.IsPrivate || repo.Owner.Visibility == api.VisibleTypePrivate
if err = UpdateRepository(ctx, forkRepos[i], true); err != nil {
return fmt.Errorf("updateRepository[%d]: %w", forkRepos[i].ID, err)
}
}

// If visibility is changed, we need to update the issue indexer.
// Since the data in the issue indexer have field to indicate if the repo is public or not.
issue_indexer.UpdateRepoIndexer(ctx, repo.ID)
}

return nil
}
21 changes: 0 additions & 21 deletions modules/repository/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,13 @@ package repository
import (
"testing"

activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"

"github.com/stretchr/testify/assert"
)

func TestUpdateRepositoryVisibilityChanged(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())

// Get sample repo and change visibility
repo, err := repo_model.GetRepositoryByID(db.DefaultContext, 9)
assert.NoError(t, err)
repo.IsPrivate = true

// Update it
err = UpdateRepository(db.DefaultContext, repo, true)
assert.NoError(t, err)

// Check visibility of action has become private
act := activities_model.Action{}
_, err = db.GetEngine(db.DefaultContext).ID(3).Get(&act)

assert.NoError(t, err)
assert.True(t, act.IsPrivate)
}

func TestGetDirectorySize(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
repo, err := repo_model.GetRepositoryByID(db.DefaultContext, 1)
Expand Down
2 changes: 1 addition & 1 deletion services/repository/adopt.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ func adoptRepository(ctx context.Context, repo *repo_model.Repository, defaultBr
return fmt.Errorf("setDefaultBranch: %w", err)
}
}
if err = repo_module.UpdateRepository(ctx, repo, false); err != nil {
if err = updateRepository(ctx, repo, false); err != nil {
return fmt.Errorf("updateRepository: %w", err)
}

Expand Down
2 changes: 1 addition & 1 deletion services/repository/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ func cleanupRepository(doer *user_model.User, repoID int64) {
}

func updateGitRepoAfterCreate(ctx context.Context, repo *repo_model.Repository) error {
if err := repo_module.CheckDaemonExportOK(ctx, repo); err != nil {
if err := checkDaemonExportOK(ctx, repo); err != nil {
return fmt.Errorf("checkDaemonExportOK: %w", err)
}

Expand Down
2 changes: 1 addition & 1 deletion services/repository/fork.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ func ConvertForkToNormalRepository(ctx context.Context, repo *repo_model.Reposit
repo.IsFork = false
repo.ForkID = 0

if err := repo_module.UpdateRepository(ctx, repo, false); err != nil {
if err := updateRepository(ctx, repo, false); err != nil {
log.Error("Unable to update repository %-v whilst converting from fork. Error: %v", repo, err)
return err
}
Expand Down
151 changes: 121 additions & 30 deletions services/repository/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,28 @@ import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
"strings"

activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/organization"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
system_model "code.gitea.io/gitea/models/system"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/graceful"
issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/queue"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
notify_service "code.gitea.io/gitea/services/notify"
pull_service "code.gitea.io/gitea/services/pull"
)
Expand Down Expand Up @@ -112,42 +119,32 @@ func Init(ctx context.Context) error {

// UpdateRepository updates a repository
func UpdateRepository(ctx context.Context, repo *repo_model.Repository, visibilityChanged bool) (err error) {
ctx, committer, err := db.TxContext(ctx)
if err != nil {
return err
}
defer committer.Close()

if err = repo_module.UpdateRepository(ctx, repo, visibilityChanged); err != nil {
return fmt.Errorf("updateRepository: %w", err)
}

return committer.Commit()
}

func UpdateRepositoryVisibility(ctx context.Context, repo *repo_model.Repository, isPrivate bool) (err error) {
ctx, committer, err := db.TxContext(ctx)
if err != nil {
return err
}

defer committer.Close()

repo.IsPrivate = isPrivate

if err = repo_module.UpdateRepository(ctx, repo, true); err != nil {
return fmt.Errorf("UpdateRepositoryVisibility: %w", err)
}

return committer.Commit()
return db.WithTx(ctx, func(ctx context.Context) error {
if err = updateRepository(ctx, repo, visibilityChanged); err != nil {
return fmt.Errorf("updateRepository: %w", err)
}
return nil
})
}

func MakeRepoPublic(ctx context.Context, repo *repo_model.Repository) (err error) {
return UpdateRepositoryVisibility(ctx, repo, false)
return db.WithTx(ctx, func(ctx context.Context) error {
repo.IsPrivate = false
if err = updateRepository(ctx, repo, true); err != nil {
return fmt.Errorf("MakeRepoPublic: %w", err)
}
return nil
})
}

func MakeRepoPrivate(ctx context.Context, repo *repo_model.Repository) (err error) {
return UpdateRepositoryVisibility(ctx, repo, true)
return db.WithTx(ctx, func(ctx context.Context) error {
repo.IsPrivate = true
if err = updateRepository(ctx, repo, true); err != nil {
return fmt.Errorf("MakeRepoPrivate: %w", err)
}
return nil
})
}

// LinkedRepository returns the linked repo if any
Expand All @@ -173,3 +170,97 @@ func LinkedRepository(ctx context.Context, a *repo_model.Attachment) (*repo_mode
}
return nil, -1, nil
}

// checkDaemonExportOK creates/removes git-daemon-export-ok for git-daemon...
func checkDaemonExportOK(ctx context.Context, repo *repo_model.Repository) error {
if err := repo.LoadOwner(ctx); err != nil {
return err
}

// Create/Remove git-daemon-export-ok for git-daemon...
daemonExportFile := filepath.Join(repo.RepoPath(), `git-daemon-export-ok`)

isExist, err := util.IsExist(daemonExportFile)
if err != nil {
log.Error("Unable to check if %s exists. Error: %v", daemonExportFile, err)
return err
}

isPublic := !repo.IsPrivate && repo.Owner.Visibility == structs.VisibleTypePublic
if !isPublic && isExist {
if err = util.Remove(daemonExportFile); err != nil {
log.Error("Failed to remove %s: %v", daemonExportFile, err)
}
} else if isPublic && !isExist {
if f, err := os.Create(daemonExportFile); err != nil {
log.Error("Failed to create %s: %v", daemonExportFile, err)
} else {
f.Close()
}
}

return nil
}

// updateRepository updates a repository with db context
func updateRepository(ctx context.Context, repo *repo_model.Repository, visibilityChanged bool) (err error) {
repo.LowerName = strings.ToLower(repo.Name)

e := db.GetEngine(ctx)

if _, err = e.ID(repo.ID).AllCols().Update(repo); err != nil {
return fmt.Errorf("update: %w", err)
}

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

if visibilityChanged {
if err = repo.LoadOwner(ctx); err != nil {
return fmt.Errorf("LoadOwner: %w", err)
}
if repo.Owner.IsOrganization() {
// Organization repository need to recalculate access table when visibility is changed.
if err = access_model.RecalculateTeamAccesses(ctx, repo, 0); err != nil {
return fmt.Errorf("recalculateTeamAccesses: %w", err)
}
}

// If repo has become private, we need to set its actions to private.
if repo.IsPrivate {
_, err = e.Where("repo_id = ?", repo.ID).Cols("is_private").Update(&activities_model.Action{
IsPrivate: true,
})
if err != nil {
return err
}

if err = repo_model.ClearRepoStars(ctx, repo.ID); err != nil {
return err
}
}

// Create/Remove git-daemon-export-ok for git-daemon...
if err := checkDaemonExportOK(ctx, repo); err != nil {
return err
}

forkRepos, err := repo_model.GetRepositoriesByForkID(ctx, repo.ID)
if err != nil {
return fmt.Errorf("getRepositoriesByForkID: %w", err)
}
for i := range forkRepos {
forkRepos[i].IsPrivate = repo.IsPrivate || repo.Owner.Visibility == structs.VisibleTypePrivate
if err = updateRepository(ctx, forkRepos[i], true); err != nil {
return fmt.Errorf("updateRepository[%d]: %w", forkRepos[i].ID, err)
}
}

// If visibility is changed, we need to update the issue indexer.
// Since the data in the issue indexer have field to indicate if the repo is public or not.
issue_indexer.UpdateRepoIndexer(ctx, repo.ID)
}

return nil
}
21 changes: 21 additions & 0 deletions services/repository/repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package repository
import (
"testing"

activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
Expand Down Expand Up @@ -40,3 +41,23 @@ func TestLinkedRepository(t *testing.T) {
})
}
}

func TestUpdateRepositoryVisibilityChanged(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())

// Get sample repo and change visibility
repo, err := repo_model.GetRepositoryByID(db.DefaultContext, 9)
assert.NoError(t, err)
repo.IsPrivate = true

// Update it
err = updateRepository(db.DefaultContext, repo, true)
assert.NoError(t, err)

// Check visibility of action has become private
act := activities_model.Action{}
_, err = db.GetEngine(db.DefaultContext).ID(3).Get(&act)

assert.NoError(t, err)
assert.True(t, act.IsPrivate)
}