Skip to content

Commit 9bb1adf

Browse files
authored
Move some repository transfer functions to service layer (#28855)
1 parent 2da233a commit 9bb1adf

File tree

8 files changed

+347
-358
lines changed

8 files changed

+347
-358
lines changed

models/repo/update.go

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package repo
66
import (
77
"context"
88
"fmt"
9-
"strings"
109
"time"
1110

1211
"code.gitea.io/gitea/models/db"
@@ -135,55 +134,6 @@ func CheckCreateRepository(ctx context.Context, doer, u *user_model.User, name s
135134
return nil
136135
}
137136

138-
// ChangeRepositoryName changes all corresponding setting from old repository name to new one.
139-
func ChangeRepositoryName(ctx context.Context, doer *user_model.User, repo *Repository, newRepoName string) (err error) {
140-
oldRepoName := repo.Name
141-
newRepoName = strings.ToLower(newRepoName)
142-
if err = IsUsableRepoName(newRepoName); err != nil {
143-
return err
144-
}
145-
146-
if err := repo.LoadOwner(ctx); err != nil {
147-
return err
148-
}
149-
150-
has, err := IsRepositoryModelOrDirExist(ctx, repo.Owner, newRepoName)
151-
if err != nil {
152-
return fmt.Errorf("IsRepositoryExist: %w", err)
153-
} else if has {
154-
return ErrRepoAlreadyExist{repo.Owner.Name, newRepoName}
155-
}
156-
157-
newRepoPath := RepoPath(repo.Owner.Name, newRepoName)
158-
if err = util.Rename(repo.RepoPath(), newRepoPath); err != nil {
159-
return fmt.Errorf("rename repository directory: %w", err)
160-
}
161-
162-
wikiPath := repo.WikiPath()
163-
isExist, err := util.IsExist(wikiPath)
164-
if err != nil {
165-
log.Error("Unable to check if %s exists. Error: %v", wikiPath, err)
166-
return err
167-
}
168-
if isExist {
169-
if err = util.Rename(wikiPath, WikiPath(repo.Owner.Name, newRepoName)); err != nil {
170-
return fmt.Errorf("rename repository wiki: %w", err)
171-
}
172-
}
173-
174-
ctx, committer, err := db.TxContext(ctx)
175-
if err != nil {
176-
return err
177-
}
178-
defer committer.Close()
179-
180-
if err := NewRedirect(ctx, repo.Owner.ID, repo.ID, oldRepoName, newRepoName); err != nil {
181-
return err
182-
}
183-
184-
return committer.Commit()
185-
}
186-
187137
// UpdateRepoSize updates the repository size, calculating it using getDirectorySize
188138
func UpdateRepoSize(ctx context.Context, repoID, gitSize, lfsSize int64) error {
189139
_, err := db.GetEngine(ctx).ID(repoID).Cols("size", "git_size", "lfs_size").NoAutoTime().Update(&Repository{

models/repo_transfer.go

Lines changed: 1 addition & 246 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,13 @@ package models
66
import (
77
"context"
88
"fmt"
9-
"os"
109

1110
"code.gitea.io/gitea/models/db"
12-
issues_model "code.gitea.io/gitea/models/issues"
1311
"code.gitea.io/gitea/models/organization"
14-
access_model "code.gitea.io/gitea/models/perm/access"
1512
repo_model "code.gitea.io/gitea/models/repo"
1613
user_model "code.gitea.io/gitea/models/user"
1714
"code.gitea.io/gitea/modules/log"
1815
"code.gitea.io/gitea/modules/timeutil"
19-
"code.gitea.io/gitea/modules/util"
2016
)
2117

2218
// RepoTransfer is used to manage repository transfers
@@ -115,32 +111,11 @@ func GetPendingRepositoryTransfer(ctx context.Context, repo *repo_model.Reposito
115111
return transfer, nil
116112
}
117113

118-
func deleteRepositoryTransfer(ctx context.Context, repoID int64) error {
114+
func DeleteRepositoryTransfer(ctx context.Context, repoID int64) error {
119115
_, err := db.GetEngine(ctx).Where("repo_id = ?", repoID).Delete(&RepoTransfer{})
120116
return err
121117
}
122118

123-
// CancelRepositoryTransfer marks the repository as ready and remove pending transfer entry,
124-
// thus cancel the transfer process.
125-
func CancelRepositoryTransfer(ctx context.Context, repo *repo_model.Repository) error {
126-
ctx, committer, err := db.TxContext(ctx)
127-
if err != nil {
128-
return err
129-
}
130-
defer committer.Close()
131-
132-
repo.Status = repo_model.RepositoryReady
133-
if err := repo_model.UpdateRepositoryCols(ctx, repo, "status"); err != nil {
134-
return err
135-
}
136-
137-
if err := deleteRepositoryTransfer(ctx, repo.ID); err != nil {
138-
return err
139-
}
140-
141-
return committer.Commit()
142-
}
143-
144119
// TestRepositoryReadyForTransfer make sure repo is ready to transfer
145120
func TestRepositoryReadyForTransfer(status repo_model.RepositoryStatus) error {
146121
switch status {
@@ -197,223 +172,3 @@ func CreatePendingRepositoryTransfer(ctx context.Context, doer, newOwner *user_m
197172
return db.Insert(ctx, transfer)
198173
})
199174
}
200-
201-
// TransferOwnership transfers all corresponding repository items from old user to new one.
202-
func TransferOwnership(ctx context.Context, doer *user_model.User, newOwnerName string, repo *repo_model.Repository) (err error) {
203-
repoRenamed := false
204-
wikiRenamed := false
205-
oldOwnerName := doer.Name
206-
207-
defer func() {
208-
if !repoRenamed && !wikiRenamed {
209-
return
210-
}
211-
212-
recoverErr := recover()
213-
if err == nil && recoverErr == nil {
214-
return
215-
}
216-
217-
if repoRenamed {
218-
if err := util.Rename(repo_model.RepoPath(newOwnerName, repo.Name), repo_model.RepoPath(oldOwnerName, repo.Name)); err != nil {
219-
log.Critical("Unable to move repository %s/%s directory from %s back to correct place %s: %v", oldOwnerName, repo.Name,
220-
repo_model.RepoPath(newOwnerName, repo.Name), repo_model.RepoPath(oldOwnerName, repo.Name), err)
221-
}
222-
}
223-
224-
if wikiRenamed {
225-
if err := util.Rename(repo_model.WikiPath(newOwnerName, repo.Name), repo_model.WikiPath(oldOwnerName, repo.Name)); err != nil {
226-
log.Critical("Unable to move wiki for repository %s/%s directory from %s back to correct place %s: %v", oldOwnerName, repo.Name,
227-
repo_model.WikiPath(newOwnerName, repo.Name), repo_model.WikiPath(oldOwnerName, repo.Name), err)
228-
}
229-
}
230-
231-
if recoverErr != nil {
232-
log.Error("Panic within TransferOwnership: %v\n%s", recoverErr, log.Stack(2))
233-
panic(recoverErr)
234-
}
235-
}()
236-
237-
ctx, committer, err := db.TxContext(ctx)
238-
if err != nil {
239-
return err
240-
}
241-
defer committer.Close()
242-
243-
sess := db.GetEngine(ctx)
244-
245-
newOwner, err := user_model.GetUserByName(ctx, newOwnerName)
246-
if err != nil {
247-
return fmt.Errorf("get new owner '%s': %w", newOwnerName, err)
248-
}
249-
newOwnerName = newOwner.Name // ensure capitalisation matches
250-
251-
// Check if new owner has repository with same name.
252-
if has, err := repo_model.IsRepositoryModelOrDirExist(ctx, newOwner, repo.Name); err != nil {
253-
return fmt.Errorf("IsRepositoryExist: %w", err)
254-
} else if has {
255-
return repo_model.ErrRepoAlreadyExist{
256-
Uname: newOwnerName,
257-
Name: repo.Name,
258-
}
259-
}
260-
261-
oldOwner := repo.Owner
262-
oldOwnerName = oldOwner.Name
263-
264-
// Note: we have to set value here to make sure recalculate accesses is based on
265-
// new owner.
266-
repo.OwnerID = newOwner.ID
267-
repo.Owner = newOwner
268-
repo.OwnerName = newOwner.Name
269-
270-
// Update repository.
271-
if _, err := sess.ID(repo.ID).Update(repo); err != nil {
272-
return fmt.Errorf("update owner: %w", err)
273-
}
274-
275-
// Remove redundant collaborators.
276-
collaborators, err := repo_model.GetCollaborators(ctx, repo.ID, db.ListOptions{})
277-
if err != nil {
278-
return fmt.Errorf("getCollaborators: %w", err)
279-
}
280-
281-
// Dummy object.
282-
collaboration := &repo_model.Collaboration{RepoID: repo.ID}
283-
for _, c := range collaborators {
284-
if c.IsGhost() {
285-
collaboration.ID = c.Collaboration.ID
286-
if _, err := sess.Delete(collaboration); err != nil {
287-
return fmt.Errorf("remove collaborator '%d': %w", c.ID, err)
288-
}
289-
collaboration.ID = 0
290-
}
291-
292-
if c.ID != newOwner.ID {
293-
isMember, err := organization.IsOrganizationMember(ctx, newOwner.ID, c.ID)
294-
if err != nil {
295-
return fmt.Errorf("IsOrgMember: %w", err)
296-
} else if !isMember {
297-
continue
298-
}
299-
}
300-
collaboration.UserID = c.ID
301-
if _, err := sess.Delete(collaboration); err != nil {
302-
return fmt.Errorf("remove collaborator '%d': %w", c.ID, err)
303-
}
304-
collaboration.UserID = 0
305-
}
306-
307-
// Remove old team-repository relations.
308-
if oldOwner.IsOrganization() {
309-
if err := organization.RemoveOrgRepo(ctx, oldOwner.ID, repo.ID); err != nil {
310-
return fmt.Errorf("removeOrgRepo: %w", err)
311-
}
312-
}
313-
314-
if newOwner.IsOrganization() {
315-
teams, err := organization.FindOrgTeams(ctx, newOwner.ID)
316-
if err != nil {
317-
return fmt.Errorf("LoadTeams: %w", err)
318-
}
319-
for _, t := range teams {
320-
if t.IncludesAllRepositories {
321-
if err := AddRepository(ctx, t, repo); err != nil {
322-
return fmt.Errorf("AddRepository: %w", err)
323-
}
324-
}
325-
}
326-
} else if err := access_model.RecalculateAccesses(ctx, repo); err != nil {
327-
// Organization called this in addRepository method.
328-
return fmt.Errorf("recalculateAccesses: %w", err)
329-
}
330-
331-
// Update repository count.
332-
if _, err := sess.Exec("UPDATE `user` SET num_repos=num_repos+1 WHERE id=?", newOwner.ID); err != nil {
333-
return fmt.Errorf("increase new owner repository count: %w", err)
334-
} else if _, err := sess.Exec("UPDATE `user` SET num_repos=num_repos-1 WHERE id=?", oldOwner.ID); err != nil {
335-
return fmt.Errorf("decrease old owner repository count: %w", err)
336-
}
337-
338-
if err := repo_model.WatchRepo(ctx, doer.ID, repo.ID, true); err != nil {
339-
return fmt.Errorf("watchRepo: %w", err)
340-
}
341-
342-
// Remove watch for organization.
343-
if oldOwner.IsOrganization() {
344-
if err := repo_model.WatchRepo(ctx, oldOwner.ID, repo.ID, false); err != nil {
345-
return fmt.Errorf("watchRepo [false]: %w", err)
346-
}
347-
}
348-
349-
// Delete labels that belong to the old organization and comments that added these labels
350-
if oldOwner.IsOrganization() {
351-
if _, err := sess.Exec(`DELETE FROM issue_label WHERE issue_label.id IN (
352-
SELECT il_too.id FROM (
353-
SELECT il_too_too.id
354-
FROM issue_label AS il_too_too
355-
INNER JOIN label ON il_too_too.label_id = label.id
356-
INNER JOIN issue on issue.id = il_too_too.issue_id
357-
WHERE
358-
issue.repo_id = ? AND ((label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != ?))
359-
) AS il_too )`, repo.ID, newOwner.ID); err != nil {
360-
return fmt.Errorf("Unable to remove old org labels: %w", err)
361-
}
362-
363-
if _, err := sess.Exec(`DELETE FROM comment WHERE comment.id IN (
364-
SELECT il_too.id FROM (
365-
SELECT com.id
366-
FROM comment AS com
367-
INNER JOIN label ON com.label_id = label.id
368-
INNER JOIN issue ON issue.id = com.issue_id
369-
WHERE
370-
com.type = ? AND issue.repo_id = ? AND ((label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != ?))
371-
) AS il_too)`, issues_model.CommentTypeLabel, repo.ID, newOwner.ID); err != nil {
372-
return fmt.Errorf("Unable to remove old org label comments: %w", err)
373-
}
374-
}
375-
376-
// Rename remote repository to new path and delete local copy.
377-
dir := user_model.UserPath(newOwner.Name)
378-
379-
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
380-
return fmt.Errorf("Failed to create dir %s: %w", dir, err)
381-
}
382-
383-
if err := util.Rename(repo_model.RepoPath(oldOwner.Name, repo.Name), repo_model.RepoPath(newOwner.Name, repo.Name)); err != nil {
384-
return fmt.Errorf("rename repository directory: %w", err)
385-
}
386-
repoRenamed = true
387-
388-
// Rename remote wiki repository to new path and delete local copy.
389-
wikiPath := repo_model.WikiPath(oldOwner.Name, repo.Name)
390-
391-
if isExist, err := util.IsExist(wikiPath); err != nil {
392-
log.Error("Unable to check if %s exists. Error: %v", wikiPath, err)
393-
return err
394-
} else if isExist {
395-
if err := util.Rename(wikiPath, repo_model.WikiPath(newOwner.Name, repo.Name)); err != nil {
396-
return fmt.Errorf("rename repository wiki: %w", err)
397-
}
398-
wikiRenamed = true
399-
}
400-
401-
if err := deleteRepositoryTransfer(ctx, repo.ID); err != nil {
402-
return fmt.Errorf("deleteRepositoryTransfer: %w", err)
403-
}
404-
repo.Status = repo_model.RepositoryReady
405-
if err := repo_model.UpdateRepositoryCols(ctx, repo, "status"); err != nil {
406-
return err
407-
}
408-
409-
// If there was previously a redirect at this location, remove it.
410-
if err := repo_model.DeleteRedirect(ctx, newOwner.ID, repo.Name); err != nil {
411-
return fmt.Errorf("delete repo redirect: %w", err)
412-
}
413-
414-
if err := repo_model.NewRedirect(ctx, oldOwner.ID, repo.ID, repo.Name, repo.Name); err != nil {
415-
return fmt.Errorf("repo_model.NewRedirect: %w", err)
416-
}
417-
418-
return committer.Commit()
419-
}

models/repo_transfer_test.go

Lines changed: 0 additions & 57 deletions
This file was deleted.

0 commit comments

Comments
 (0)