@@ -6,17 +6,13 @@ package models
66import (
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
145120func 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- }
0 commit comments