From 0a542dd59f8061797976f33690bf10357aa0b0ad Mon Sep 17 00:00:00 2001
From: zeripath <art27@cantab.net>
Date: Tue, 14 Sep 2021 18:07:08 +0100
Subject: [PATCH] Decrement Fork Num when converting from Fork (#17035)

When converting repositories from forks to normal the root NumFork needs to be
decremented too.

Fix #17026

Signed-off-by: Andrew Thornton <art27@cantab.net>
---
 models/repo.go              |  6 ++++++
 modules/repository/fork.go  | 31 +++++++++++++++++++++++++++++++
 routers/web/repo/setting.go |  6 ++----
 3 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/models/repo.go b/models/repo.go
index 23287067e2..709fe6ab0e 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -1209,6 +1209,12 @@ func IncrementRepoForkNum(ctx DBContext, repoID int64) error {
 	return err
 }
 
+// DecrementRepoForkNum decrement repository fork number
+func DecrementRepoForkNum(ctx DBContext, repoID int64) error {
+	_, err := ctx.e.Exec("UPDATE `repository` SET num_forks=num_forks-1 WHERE id=?", repoID)
+	return err
+}
+
 // ChangeRepositoryName changes all corresponding setting from old repository name to new one.
 func ChangeRepositoryName(doer *User, repo *Repository, newRepoName string) (err error) {
 	oldRepoName := repo.Name
diff --git a/modules/repository/fork.go b/modules/repository/fork.go
index 4e750dec08..b154cc5ccd 100644
--- a/modules/repository/fork.go
+++ b/modules/repository/fork.go
@@ -132,3 +132,34 @@ func ForkRepository(doer, owner *models.User, opts models.ForkRepoOptions) (_ *m
 
 	return repo, nil
 }
+
+// ConvertForkToNormalRepository convert the provided repo from a forked repo to normal repo
+func ConvertForkToNormalRepository(repo *models.Repository) error {
+	err := models.WithTx(func(ctx models.DBContext) error {
+		repo, err := models.GetRepositoryByIDCtx(ctx, repo.ID)
+		if err != nil {
+			return err
+		}
+
+		if !repo.IsFork {
+			return nil
+		}
+
+		if err := models.DecrementRepoForkNum(ctx, repo.ForkID); err != nil {
+			log.Error("Unable to decrement repo fork num for old root repo %d of repository %-v whilst converting from fork. Error: %v", repo.ForkID, repo, err)
+			return err
+		}
+
+		repo.IsFork = false
+		repo.ForkID = 0
+
+		if err := models.UpdateRepositoryCtx(ctx, repo, false); err != nil {
+			log.Error("Unable to update repository %-v whilst converting from fork. Error: %v", repo, err)
+			return err
+		}
+
+		return nil
+	})
+
+	return err
+}
diff --git a/routers/web/repo/setting.go b/routers/web/repo/setting.go
index 72bacebd27..ad7a330381 100644
--- a/routers/web/repo/setting.go
+++ b/routers/web/repo/setting.go
@@ -555,10 +555,8 @@ func SettingsPost(ctx *context.Context) {
 			return
 		}
 
-		repo.IsFork = false
-		repo.ForkID = 0
-		if err := models.UpdateRepository(repo, false); err != nil {
-			log.Error("Unable to update repository %-v whilst converting from fork", repo)
+		if err := repository.ConvertForkToNormalRepository(repo); err != nil {
+			log.Error("Unable to convert repository %-v from fork. Error: %v", repo, err)
 			ctx.ServerError("Convert Fork", err)
 			return
 		}