diff options
author | Lunny Xiao <xiaolunwen@gmail.com> | 2021-03-05 10:28:52 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-05 03:28:52 +0100 |
commit | 7525450232337a5c7144565ba92e2a7c18082e1d (patch) | |
tree | 2c750faff168e009813ef4bc6b96fbb077a861d0 | |
parent | 0a8a3ab0f5b46cc5280976c07a16d8721186f9f6 (diff) | |
download | gitea-7525450232337a5c7144565ba92e2a7c18082e1d.tar.gz gitea-7525450232337a5c7144565ba92e2a7c18082e1d.zip |
When transfering repository and database transaction failed, rollback the renames (#14864)
Fix #14821
Co-authored-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: 6543 <6543@obermui.de>
-rw-r--r-- | models/repo_transfer.go | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/models/repo_transfer.go b/models/repo_transfer.go index cf1e16b9c3..9f8fd649b6 100644 --- a/models/repo_transfer.go +++ b/models/repo_transfer.go @@ -195,7 +195,39 @@ func CreatePendingRepositoryTransfer(doer, newOwner *User, repoID int64, teams [ } // TransferOwnership transfers all corresponding repository items from old user to new one. -func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error { +func TransferOwnership(doer *User, newOwnerName string, repo *Repository) (err error) { + repoRenamed := false + wikiRenamed := false + oldOwnerName := doer.Name + + defer func() { + if !repoRenamed && !wikiRenamed { + return + } + + recoverErr := recover() + if err == nil && recoverErr == nil { + return + } + + if repoRenamed { + if err := os.Rename(RepoPath(newOwnerName, repo.Name), RepoPath(oldOwnerName, repo.Name)); err != nil { + 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) + } + } + + if wikiRenamed { + if err := os.Rename(WikiPath(newOwnerName, repo.Name), WikiPath(oldOwnerName, repo.Name)); err != nil { + 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) + } + } + + if recoverErr != nil { + log.Error("Panic within TransferOwnership: %v\n%s", recoverErr, log.Stack(2)) + panic(recoverErr) + } + }() + sess := x.NewSession() defer sess.Close() if err := sess.Begin(); err != nil { @@ -206,6 +238,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error if err != nil { return fmt.Errorf("get new owner '%s': %v", newOwnerName, err) } + newOwnerName = newOwner.Name // ensure capitalisation matches // Check if new owner has repository with same name. if has, err := isRepositoryExist(sess, newOwner, repo.Name); err != nil { @@ -215,6 +248,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error } oldOwner := repo.Owner + oldOwnerName = oldOwner.Name // Note: we have to set value here to make sure recalculate accesses is based on // new owner. @@ -301,6 +335,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error if err := os.Rename(RepoPath(oldOwner.Name, repo.Name), RepoPath(newOwner.Name, repo.Name)); err != nil { return fmt.Errorf("rename repository directory: %v", err) } + repoRenamed = true // Rename remote wiki repository to new path and delete local copy. wikiPath := WikiPath(oldOwner.Name, repo.Name) @@ -312,6 +347,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error if err := os.Rename(wikiPath, WikiPath(newOwner.Name, repo.Name)); err != nil { return fmt.Errorf("rename repository wiki: %v", err) } + wikiRenamed = true } if err := deleteRepositoryTransfer(sess, repo.ID); err != nil { |