Skip to content

Commit 9e85358

Browse files
authored
Move some repositories' operations to a standalone service package (#8557)
* Move some repositories' operations to a standalone service package * improve code * remove unused codes * add rollback when fork failed * add repo when return
1 parent d2d5910 commit 9e85358

File tree

10 files changed

+179
-89
lines changed

10 files changed

+179
-89
lines changed

models/repo.go

Lines changed: 35 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,28 @@ func (repo *Repository) CanUserFork(user *User) (bool, error) {
742742
return false, nil
743743
}
744744

745+
// CanUserDelete returns true if user could delete the repository
746+
func (repo *Repository) CanUserDelete(user *User) (bool, error) {
747+
if user.IsAdmin || user.ID == repo.OwnerID {
748+
return true, nil
749+
}
750+
751+
if err := repo.GetOwner(); err != nil {
752+
return false, err
753+
}
754+
755+
if repo.Owner.IsOrganization() {
756+
isOwner, err := repo.Owner.IsOwnedBy(user.ID)
757+
if err != nil {
758+
return false, err
759+
} else if isOwner {
760+
return true, nil
761+
}
762+
}
763+
764+
return false, nil
765+
}
766+
745767
// CanEnablePulls returns true if repository meets the requirements of accepting pulls.
746768
func (repo *Repository) CanEnablePulls() bool {
747769
return !repo.IsMirror && !repo.IsEmpty
@@ -1430,15 +1452,9 @@ func createRepository(e *xorm.Session, doer, u *User, repo *Repository) (err err
14301452
t, err := u.getOwnerTeam(e)
14311453
if err != nil {
14321454
return fmt.Errorf("getOwnerTeam: %v", err)
1433-
} else if err = t.addRepository(e, repo); err != nil {
1455+
}
1456+
if err = t.addRepository(e, repo); err != nil {
14341457
return fmt.Errorf("addRepository: %v", err)
1435-
} else if err = prepareWebhooks(e, repo, HookEventRepository, &api.RepositoryPayload{
1436-
Action: api.HookRepoCreated,
1437-
Repository: repo.innerAPIFormat(e, AccessModeOwner, false),
1438-
Organization: u.APIFormat(),
1439-
Sender: doer.APIFormat(),
1440-
}); err != nil {
1441-
return fmt.Errorf("prepareWebhooks: %v", err)
14421458
}
14431459
} else if err = repo.recalculateAccesses(e); err != nil {
14441460
// Organization automatically called this in addRepository method.
@@ -1522,11 +1538,6 @@ func CreateRepository(doer, u *User, opts CreateRepoOptions) (_ *Repository, err
15221538
return nil, err
15231539
}
15241540

1525-
// Add to hook queue for created repo after session commit.
1526-
if u.IsOrganization() {
1527-
go HookQueue.Add(repo.ID)
1528-
}
1529-
15301541
return repo, err
15311542
}
15321543

@@ -2044,18 +2055,6 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
20442055
return fmt.Errorf("Commit: %v", err)
20452056
}
20462057

2047-
if org.IsOrganization() {
2048-
if err = PrepareWebhooks(repo, HookEventRepository, &api.RepositoryPayload{
2049-
Action: api.HookRepoDeleted,
2050-
Repository: repo.APIFormat(AccessModeOwner),
2051-
Organization: org.APIFormat(),
2052-
Sender: doer.APIFormat(),
2053-
}); err != nil {
2054-
return err
2055-
}
2056-
go HookQueue.Add(repo.ID)
2057-
}
2058-
20592058
if len(repo.Avatar) > 0 {
20602059
avatarPath := repo.CustomAvatarPath()
20612060
if com.IsExist(avatarPath) {
@@ -2065,7 +2064,6 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
20652064
}
20662065
}
20672066

2068-
DeleteRepoFromIndexer(repo)
20692067
return nil
20702068
}
20712069

@@ -2521,22 +2519,22 @@ func HasForkedRepo(ownerID, repoID int64) (*Repository, bool) {
25212519
}
25222520

25232521
// ForkRepository forks a repository
2524-
func ForkRepository(doer, u *User, oldRepo *Repository, name, desc string) (_ *Repository, err error) {
2525-
forkedRepo, err := oldRepo.GetUserFork(u.ID)
2522+
func ForkRepository(doer, owner *User, oldRepo *Repository, name, desc string) (_ *Repository, err error) {
2523+
forkedRepo, err := oldRepo.GetUserFork(owner.ID)
25262524
if err != nil {
25272525
return nil, err
25282526
}
25292527
if forkedRepo != nil {
25302528
return nil, ErrForkAlreadyExist{
2531-
Uname: u.Name,
2529+
Uname: owner.Name,
25322530
RepoName: oldRepo.FullName(),
25332531
ForkName: forkedRepo.FullName(),
25342532
}
25352533
}
25362534

25372535
repo := &Repository{
2538-
OwnerID: u.ID,
2539-
Owner: u,
2536+
OwnerID: owner.ID,
2537+
Owner: owner,
25402538
Name: name,
25412539
LowerName: strings.ToLower(name),
25422540
Description: desc,
@@ -2553,17 +2551,17 @@ func ForkRepository(doer, u *User, oldRepo *Repository, name, desc string) (_ *R
25532551
return nil, err
25542552
}
25552553

2556-
if err = createRepository(sess, doer, u, repo); err != nil {
2554+
if err = createRepository(sess, doer, owner, repo); err != nil {
25572555
return nil, err
25582556
}
25592557

25602558
if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?", oldRepo.ID); err != nil {
25612559
return nil, err
25622560
}
25632561

2564-
repoPath := RepoPath(u.Name, repo.Name)
2562+
repoPath := RepoPath(owner.Name, repo.Name)
25652563
_, stderr, err := process.GetManager().ExecTimeout(10*time.Minute,
2566-
fmt.Sprintf("ForkRepository(git clone): %s/%s", u.Name, repo.Name),
2564+
fmt.Sprintf("ForkRepository(git clone): %s/%s", owner.Name, repo.Name),
25672565
git.GitExecutable, "clone", "--bare", oldRepo.repoPath(sess), repoPath)
25682566
if err != nil {
25692567
return nil, fmt.Errorf("git clone: %v", stderr)
@@ -2586,24 +2584,6 @@ func ForkRepository(doer, u *User, oldRepo *Repository, name, desc string) (_ *R
25862584
return nil, err
25872585
}
25882586

2589-
oldMode, _ := AccessLevel(doer, oldRepo)
2590-
mode, _ := AccessLevel(doer, repo)
2591-
2592-
if err = PrepareWebhooks(oldRepo, HookEventFork, &api.ForkPayload{
2593-
Forkee: oldRepo.APIFormat(oldMode),
2594-
Repo: repo.APIFormat(mode),
2595-
Sender: doer.APIFormat(),
2596-
}); err != nil {
2597-
log.Error("PrepareWebhooks [repo_id: %d]: %v", oldRepo.ID, err)
2598-
} else {
2599-
go HookQueue.Add(oldRepo.ID)
2600-
}
2601-
2602-
// Add to hook queue for created repo after session commit.
2603-
if u.IsOrganization() {
2604-
go HookQueue.Add(repo.ID)
2605-
}
2606-
26072587
if err = repo.UpdateSize(); err != nil {
26082588
log.Error("Failed to update size for repository: %v", err)
26092589
}
@@ -2612,20 +2592,19 @@ func ForkRepository(doer, u *User, oldRepo *Repository, name, desc string) (_ *R
26122592
sess2 := x.NewSession()
26132593
defer sess2.Close()
26142594
if err = sess2.Begin(); err != nil {
2615-
return nil, err
2595+
return repo, err
26162596
}
26172597

26182598
var lfsObjects []*LFSMetaObject
2619-
26202599
if err = sess2.Where("repository_id=?", oldRepo.ID).Find(&lfsObjects); err != nil {
2621-
return nil, err
2600+
return repo, err
26222601
}
26232602

26242603
for _, v := range lfsObjects {
26252604
v.ID = 0
26262605
v.RepositoryID = repo.ID
26272606
if _, err = sess2.Insert(v); err != nil {
2628-
return nil, err
2607+
return repo, err
26292608
}
26302609
}
26312610

modules/notification/indexer/indexer.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ func (r *indexerNotifier) NotifyDeleteComment(doer *models.User, comment *models
9898

9999
func (r *indexerNotifier) NotifyDeleteRepository(doer *models.User, repo *models.Repository) {
100100
issue_indexer.DeleteRepoIssueIndexer(repo)
101+
models.DeleteRepoFromIndexer(repo)
101102
}
102103

103104
func (r *indexerNotifier) NotifyIssueChangeContent(doer *models.User, issue *models.Issue, oldContent string) {

modules/notification/webhook/webhook.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,67 @@ func (m *webhookNotifier) NotifyIssueClearLabels(doer *models.User, issue *model
6565
go models.HookQueue.Add(issue.RepoID)
6666
}
6767
}
68+
69+
func (m *webhookNotifier) NotifyForkRepository(doer *models.User, oldRepo, repo *models.Repository) {
70+
oldMode, _ := models.AccessLevel(doer, oldRepo)
71+
mode, _ := models.AccessLevel(doer, repo)
72+
73+
// forked webhook
74+
if err := models.PrepareWebhooks(oldRepo, models.HookEventFork, &api.ForkPayload{
75+
Forkee: oldRepo.APIFormat(oldMode),
76+
Repo: repo.APIFormat(mode),
77+
Sender: doer.APIFormat(),
78+
}); err != nil {
79+
log.Error("PrepareWebhooks [repo_id: %d]: %v", oldRepo.ID, err)
80+
} else {
81+
go models.HookQueue.Add(oldRepo.ID)
82+
}
83+
84+
u := repo.MustOwner()
85+
86+
// Add to hook queue for created repo after session commit.
87+
if u.IsOrganization() {
88+
if err := models.PrepareWebhooks(repo, models.HookEventRepository, &api.RepositoryPayload{
89+
Action: api.HookRepoCreated,
90+
Repository: repo.APIFormat(models.AccessModeOwner),
91+
Organization: u.APIFormat(),
92+
Sender: doer.APIFormat(),
93+
}); err != nil {
94+
log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
95+
} else {
96+
go models.HookQueue.Add(repo.ID)
97+
}
98+
}
99+
}
100+
101+
func (m *webhookNotifier) NotifyCreateRepository(doer *models.User, u *models.User, repo *models.Repository) {
102+
// Add to hook queue for created repo after session commit.
103+
if u.IsOrganization() {
104+
if err := models.PrepareWebhooks(repo, models.HookEventRepository, &api.RepositoryPayload{
105+
Action: api.HookRepoCreated,
106+
Repository: repo.APIFormat(models.AccessModeOwner),
107+
Organization: u.APIFormat(),
108+
Sender: doer.APIFormat(),
109+
}); err != nil {
110+
log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
111+
} else {
112+
go models.HookQueue.Add(repo.ID)
113+
}
114+
}
115+
}
116+
117+
func (m *webhookNotifier) NotifyDeleteRepository(doer *models.User, repo *models.Repository) {
118+
u := repo.MustOwner()
119+
120+
if u.IsOrganization() {
121+
if err := models.PrepareWebhooks(repo, models.HookEventRepository, &api.RepositoryPayload{
122+
Action: api.HookRepoDeleted,
123+
Repository: repo.APIFormat(models.AccessModeOwner),
124+
Organization: u.APIFormat(),
125+
Sender: doer.APIFormat(),
126+
}); err != nil {
127+
log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
128+
}
129+
go models.HookQueue.Add(repo.ID)
130+
}
131+
}

routers/admin/repos.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"code.gitea.io/gitea/modules/log"
1212
"code.gitea.io/gitea/modules/setting"
1313
"code.gitea.io/gitea/routers"
14+
repo_service "code.gitea.io/gitea/services/repository"
1415
)
1516

1617
const (
@@ -38,7 +39,7 @@ func DeleteRepo(ctx *context.Context) {
3839
return
3940
}
4041

41-
if err := models.DeleteRepository(ctx.User, repo.MustOwner().ID, repo.ID); err != nil {
42+
if err := repo_service.DeleteRepository(ctx.User, repo); err != nil {
4243
ctx.ServerError("DeleteRepository", err)
4344
return
4445
}

routers/api/v1/repo/fork.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"code.gitea.io/gitea/models"
99
"code.gitea.io/gitea/modules/context"
1010
api "code.gitea.io/gitea/modules/structs"
11+
repo_service "code.gitea.io/gitea/services/repository"
1112
)
1213

1314
// ListForks list a repository's forks
@@ -97,10 +98,12 @@ func CreateFork(ctx *context.APIContext, form api.CreateForkOption) {
9798
}
9899
forker = org
99100
}
100-
fork, err := models.ForkRepository(ctx.User, forker, repo, repo.Name, repo.Description)
101+
102+
fork, err := repo_service.ForkRepository(ctx.User, forker, repo, repo.Name, repo.Description)
101103
if err != nil {
102104
ctx.Error(500, "ForkRepository", err)
103105
return
104106
}
107+
105108
ctx.JSON(202, fork.APIFormat(models.AccessModeOwner))
106109
}

routers/api/v1/repo/repo.go

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"code.gitea.io/gitea/modules/validation"
2525
"code.gitea.io/gitea/routers/api/v1/convert"
2626
mirror_service "code.gitea.io/gitea/services/mirror"
27+
repo_service "code.gitea.io/gitea/services/repository"
2728
)
2829

2930
var searchOrderByMap = map[string]map[string]models.SearchOrderBy{
@@ -207,7 +208,7 @@ func CreateUserRepo(ctx *context.APIContext, owner *models.User, opt api.CreateR
207208
if opt.AutoInit && opt.Readme == "" {
208209
opt.Readme = "Default"
209210
}
210-
repo, err := models.CreateRepository(ctx.User, owner, models.CreateRepoOptions{
211+
repo, err := repo_service.CreateRepository(ctx.User, owner, models.CreateRepoOptions{
211212
Name: opt.Name,
212213
Description: opt.Description,
213214
IssueLabels: opt.IssueLabels,
@@ -224,18 +225,11 @@ func CreateUserRepo(ctx *context.APIContext, owner *models.User, opt api.CreateR
224225
models.IsErrNamePatternNotAllowed(err) {
225226
ctx.Error(422, "", err)
226227
} else {
227-
if repo != nil {
228-
if err = models.DeleteRepository(ctx.User, ctx.User.ID, repo.ID); err != nil {
229-
log.Error("DeleteRepository: %v", err)
230-
}
231-
}
232228
ctx.Error(500, "CreateRepository", err)
233229
}
234230
return
235231
}
236232

237-
notification.NotifyCreateRepository(ctx.User, owner, repo)
238-
239233
ctx.JSON(201, repo.APIFormat(models.AccessModeOwner))
240234
}
241235

@@ -433,7 +427,7 @@ func Migrate(ctx *context.APIContext, form auth.MigrateRepoForm) {
433427

434428
repo, err := migrations.MigrateRepository(ctx.User, ctxUser.Name, opts)
435429
if err == nil {
436-
notification.NotifyCreateRepository(ctx.User, ctxUser, repo)
430+
notification.NotifyMigrateRepository(ctx.User, ctxUser, repo)
437431

438432
log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName)
439433
ctx.JSON(201, repo.APIFormat(models.AccessModeAdmin))
@@ -876,18 +870,16 @@ func Delete(ctx *context.APIContext) {
876870
owner := ctx.Repo.Owner
877871
repo := ctx.Repo.Repository
878872

879-
if owner.IsOrganization() && !ctx.User.IsAdmin {
880-
isOwner, err := owner.IsOwnedBy(ctx.User.ID)
881-
if err != nil {
882-
ctx.Error(500, "IsOwnedBy", err)
883-
return
884-
} else if !isOwner {
885-
ctx.Error(403, "", "Given user is not owner of organization.")
886-
return
887-
}
873+
canDelete, err := repo.CanUserDelete(ctx.User)
874+
if err != nil {
875+
ctx.Error(500, "CanUserDelete", err)
876+
return
877+
} else if !canDelete {
878+
ctx.Error(403, "", "Given user is not owner of organization.")
879+
return
888880
}
889881

890-
if err := models.DeleteRepository(ctx.User, owner.ID, repo.ID); err != nil {
882+
if err := repo_service.DeleteRepository(ctx.User, repo); err != nil {
891883
ctx.Error(500, "DeleteRepository", err)
892884
return
893885
}

routers/repo/pull.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"code.gitea.io/gitea/services/gitdiff"
2727
issue_service "code.gitea.io/gitea/services/issue"
2828
pull_service "code.gitea.io/gitea/services/pull"
29+
repo_service "code.gitea.io/gitea/services/repository"
2930

3031
"github.com/unknwon/com"
3132
)
@@ -209,7 +210,7 @@ func ForkPost(ctx *context.Context, form auth.CreateRepoForm) {
209210
}
210211
}
211212

212-
repo, err := models.ForkRepository(ctx.User, ctxUser, forkRepo, form.RepoName, form.Description)
213+
repo, err := repo_service.ForkRepository(ctx.User, ctxUser, forkRepo, form.RepoName, form.Description)
213214
if err != nil {
214215
ctx.Data["Err_RepoName"] = true
215216
switch {

0 commit comments

Comments
 (0)