From a5604b161100ca8723c016688f61003dc138316a Mon Sep 17 00:00:00 2001
From: "James E. Blair" <corvus@inaugust.com>
Date: Sat, 2 Mar 2019 05:07:19 -0800
Subject: [PATCH] Fix renames over redirects (#6216)

In #6211, we started creating repo_redirects for ownership transfers,
however that opens an edge case where a user might perform the
following sequence:

rename org1/repo1 -> org1/repo2  (creates org1/repo1 redirect)
transfer org2/repo1 -> org1/repo1 (org1/repo1 redirect continues to exist)
rename org1/repo1 -> org1/repo3 (fails due to existing org1/repo1 redirect)

This change ensures that each time we rename or transfer a repo,
we delete any existing redirects at the target location.  This
already happens when a new repo is created.  By doing this we ensure
that we'll never have both a repo and a redirect at the same location.

Signed-off-by: James E. Blair <jeblair@redhat.com>
---
 models/repo.go | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/models/repo.go b/models/repo.go
index 848a76fe88..4d7320a789 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -1564,6 +1564,11 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error
 		}
 	}
 
+	// If there was previously a redirect at this location, remove it.
+	if err = deleteRepoRedirect(sess, newOwner.ID, repo.Name); err != nil {
+		return fmt.Errorf("delete repo redirect: %v", err)
+	}
+
 	return sess.Commit()
 }
 
@@ -1614,7 +1619,18 @@ func ChangeRepositoryName(u *User, oldRepoName, newRepoName string) (err error)
 		RemoveAllWithNotice("Delete repository wiki local copy", repo.LocalWikiPath())
 	}
 
-	return nil
+	sess := x.NewSession()
+	defer sess.Close()
+	if err = sess.Begin(); err != nil {
+		return fmt.Errorf("sess.Begin: %v", err)
+	}
+
+	// If there was previously a redirect at this location, remove it.
+	if err = deleteRepoRedirect(sess, u.ID, newRepoName); err != nil {
+		return fmt.Errorf("delete repo redirect: %v", err)
+	}
+
+	return sess.Commit()
 }
 
 func getRepositoriesByForkID(e Engine, forkID int64) ([]*Repository, error) {