@@ -6,17 +6,13 @@ package models
6
6
import (
7
7
"context"
8
8
"fmt"
9
- "os"
10
9
11
10
"code.gitea.io/gitea/models/db"
12
- issues_model "code.gitea.io/gitea/models/issues"
13
11
"code.gitea.io/gitea/models/organization"
14
- access_model "code.gitea.io/gitea/models/perm/access"
15
12
repo_model "code.gitea.io/gitea/models/repo"
16
13
user_model "code.gitea.io/gitea/models/user"
17
14
"code.gitea.io/gitea/modules/log"
18
15
"code.gitea.io/gitea/modules/timeutil"
19
- "code.gitea.io/gitea/modules/util"
20
16
)
21
17
22
18
// RepoTransfer is used to manage repository transfers
@@ -115,32 +111,11 @@ func GetPendingRepositoryTransfer(ctx context.Context, repo *repo_model.Reposito
115
111
return transfer , nil
116
112
}
117
113
118
- func deleteRepositoryTransfer (ctx context.Context , repoID int64 ) error {
114
+ func DeleteRepositoryTransfer (ctx context.Context , repoID int64 ) error {
119
115
_ , err := db .GetEngine (ctx ).Where ("repo_id = ?" , repoID ).Delete (& RepoTransfer {})
120
116
return err
121
117
}
122
118
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
-
144
119
// TestRepositoryReadyForTransfer make sure repo is ready to transfer
145
120
func TestRepositoryReadyForTransfer (status repo_model.RepositoryStatus ) error {
146
121
switch status {
@@ -197,223 +172,3 @@ func CreatePendingRepositoryTransfer(ctx context.Context, doer, newOwner *user_m
197
172
return db .Insert (ctx , transfer )
198
173
})
199
174
}
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