Skip to content

Commit 74dc223

Browse files
6543lunnyzeripath
authored
When transfering repository and database transaction failed, rollback the renames (#14864) (#14902)
Fix #14821 Co-authored-by: Andrew Thornton <[email protected]> Co-authored-by: 6543 <[email protected]> Co-authored-by: Lunny Xiao <[email protected]> Co-authored-by: Andrew Thornton <[email protected]>
1 parent 7d3e174 commit 74dc223

File tree

1 file changed

+42
-6
lines changed

1 file changed

+42
-6
lines changed

models/repo.go

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,11 +1290,44 @@ func IncrementRepoForkNum(ctx DBContext, repoID int64) error {
12901290
}
12911291

12921292
// TransferOwnership transfers all corresponding setting from old user to new one.
1293-
func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error {
1293+
func TransferOwnership(doer *User, newOwnerName string, repo *Repository) (err error) {
1294+
repoRenamed := false
1295+
wikiRenamed := false
1296+
oldOwnerName := doer.Name
1297+
1298+
defer func() {
1299+
if !repoRenamed && !wikiRenamed {
1300+
return
1301+
}
1302+
1303+
recoverErr := recover()
1304+
if err == nil && recoverErr == nil {
1305+
return
1306+
}
1307+
1308+
if repoRenamed {
1309+
if err := os.Rename(RepoPath(newOwnerName, repo.Name), RepoPath(oldOwnerName, repo.Name)); err != nil {
1310+
log.Critical("Unable to move repository %s/%s directory from %s back to correct place %s: %v", oldOwnerName, repo.Name, RepoPath(newOwnerName, repo.Name), RepoPath(oldOwnerName, repo.Name), err)
1311+
}
1312+
}
1313+
1314+
if wikiRenamed {
1315+
if err := os.Rename(WikiPath(newOwnerName, repo.Name), WikiPath(oldOwnerName, repo.Name)); err != nil {
1316+
log.Critical("Unable to move wiki for repository %s/%s directory from %s back to correct place %s: %v", oldOwnerName, repo.Name, WikiPath(newOwnerName, repo.Name), WikiPath(oldOwnerName, repo.Name), err)
1317+
}
1318+
}
1319+
1320+
if recoverErr != nil {
1321+
log.Error("Panic within TransferOwnership: %v\n%s", recoverErr, log.Stack(2))
1322+
panic(recoverErr)
1323+
}
1324+
}()
1325+
12941326
newOwner, err := GetUserByName(newOwnerName)
12951327
if err != nil {
12961328
return fmt.Errorf("get new owner '%s': %v", newOwnerName, err)
12971329
}
1330+
newOwnerName = newOwner.Name // ensure capitalisation matches
12981331

12991332
// Check if new owner has repository with same name.
13001333
has, err := IsRepositoryExist(newOwner, repo.Name)
@@ -1311,6 +1344,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error
13111344
}
13121345

13131346
oldOwner := repo.Owner
1347+
oldOwnerName = oldOwner.Name
13141348

13151349
// Note: we have to set value here to make sure recalculate accesses is based on
13161350
// new owner.
@@ -1370,9 +1404,9 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error
13701404
}
13711405

13721406
// Update repository count.
1373-
if _, err = sess.Exec("UPDATE `user` SET num_repos=num_repos+1 WHERE id=?", newOwner.ID); err != nil {
1407+
if _, err := sess.Exec("UPDATE `user` SET num_repos=num_repos+1 WHERE id=?", newOwner.ID); err != nil {
13741408
return fmt.Errorf("increase new owner repository count: %v", err)
1375-
} else if _, err = sess.Exec("UPDATE `user` SET num_repos=num_repos-1 WHERE id=?", oldOwner.ID); err != nil {
1409+
} else if _, err := sess.Exec("UPDATE `user` SET num_repos=num_repos-1 WHERE id=?", oldOwner.ID); err != nil {
13761410
return fmt.Errorf("decrease old owner repository count: %v", err)
13771411
}
13781412

@@ -1382,7 +1416,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error
13821416

13831417
// Remove watch for organization.
13841418
if oldOwner.IsOrganization() {
1385-
if err = watchRepo(sess, oldOwner.ID, repo.ID, false); err != nil {
1419+
if err := watchRepo(sess, oldOwner.ID, repo.ID, false); err != nil {
13861420
return fmt.Errorf("watchRepo [false]: %v", err)
13871421
}
13881422
}
@@ -1394,16 +1428,18 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error
13941428
return fmt.Errorf("Failed to create dir %s: %v", dir, err)
13951429
}
13961430

1397-
if err = os.Rename(RepoPath(oldOwner.Name, repo.Name), RepoPath(newOwner.Name, repo.Name)); err != nil {
1431+
if err := os.Rename(RepoPath(oldOwner.Name, repo.Name), RepoPath(newOwner.Name, repo.Name)); err != nil {
13981432
return fmt.Errorf("rename repository directory: %v", err)
13991433
}
1434+
repoRenamed = true
14001435

14011436
// Rename remote wiki repository to new path and delete local copy.
14021437
wikiPath := WikiPath(oldOwner.Name, repo.Name)
14031438
if com.IsExist(wikiPath) {
1404-
if err = os.Rename(wikiPath, WikiPath(newOwner.Name, repo.Name)); err != nil {
1439+
if err := os.Rename(wikiPath, WikiPath(newOwner.Name, repo.Name)); err != nil {
14051440
return fmt.Errorf("rename repository wiki: %v", err)
14061441
}
1442+
wikiRenamed = true
14071443
}
14081444

14091445
// If there was previously a redirect at this location, remove it.

0 commit comments

Comments
 (0)