From e2786147539909eaef2bc39fb728a10b88277d31 Mon Sep 17 00:00:00 2001
From: 6543 <6543@obermui.de>
Date: Sat, 8 May 2021 14:11:36 +0200
Subject: [PATCH] [API] make change repo settings work on empty repos (#15778)

* API: Fix #15602

* Add TEST
---
 integrations/api_repo_edit_test.go | 23 +++++++++++++++++++----
 routers/api/v1/api.go              |  2 +-
 routers/api/v1/repo/repo.go        | 16 ++++++++--------
 3 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/integrations/api_repo_edit_test.go b/integrations/api_repo_edit_test.go
index c1b513d075..618c1f0ad0 100644
--- a/integrations/api_repo_edit_test.go
+++ b/integrations/api_repo_edit_test.go
@@ -130,11 +130,14 @@ func getNewRepoEditOption(opts *api.EditRepoOption) *api.EditRepoOption {
 
 func TestAPIRepoEdit(t *testing.T) {
 	onGiteaRun(t, func(t *testing.T, u *url.URL) {
+		bFalse, bTrue := false, true
+
 		user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)               // owner of the repo1 & repo16
 		user3 := models.AssertExistsAndLoadBean(t, &models.User{ID: 3}).(*models.User)               // owner of the repo3, is an org
 		user4 := models.AssertExistsAndLoadBean(t, &models.User{ID: 4}).(*models.User)               // owner of neither repos
 		repo1 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)   // public repo
 		repo3 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 3}).(*models.Repository)   // public repo
+		repo15 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 15}).(*models.Repository) // empty repo
 		repo16 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 16}).(*models.Repository) // private repo
 
 		// Get user2's token
@@ -286,9 +289,8 @@ func TestAPIRepoEdit(t *testing.T) {
 		// Test making a repo public that is private
 		repo16 = models.AssertExistsAndLoadBean(t, &models.Repository{ID: 16}).(*models.Repository)
 		assert.True(t, repo16.IsPrivate)
-		private := false
 		repoEditOption = &api.EditRepoOption{
-			Private: &private,
+			Private: &bFalse,
 		}
 		url = fmt.Sprintf("/api/v1/repos/%s/%s?token=%s", user2.Name, repo16.Name, token2)
 		req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption)
@@ -296,11 +298,24 @@ func TestAPIRepoEdit(t *testing.T) {
 		repo16 = models.AssertExistsAndLoadBean(t, &models.Repository{ID: 16}).(*models.Repository)
 		assert.False(t, repo16.IsPrivate)
 		// Make it private again
-		private = true
-		repoEditOption.Private = &private
+		repoEditOption.Private = &bTrue
 		req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption)
 		_ = session.MakeRequest(t, req, http.StatusOK)
 
+		// Test to change empty repo
+		assert.False(t, repo15.IsArchived)
+		url = fmt.Sprintf("/api/v1/repos/%s/%s?token=%s", user2.Name, repo15.Name, token2)
+		req = NewRequestWithJSON(t, "PATCH", url, &api.EditRepoOption{
+			Archived: &bTrue,
+		})
+		_ = session.MakeRequest(t, req, http.StatusOK)
+		repo15 = models.AssertExistsAndLoadBean(t, &models.Repository{ID: 15}).(*models.Repository)
+		assert.True(t, repo15.IsArchived)
+		req = NewRequestWithJSON(t, "PATCH", url, &api.EditRepoOption{
+			Archived: &bFalse,
+		})
+		_ = session.MakeRequest(t, req, http.StatusOK)
+
 		// Test using org repo "user3/repo3" where user2 is a collaborator
 		origRepoEditOption = getRepoEditOptionFromRepo(repo3)
 		repoEditOption = getNewRepoEditOption(origRepoEditOption)
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 05b95d6d5f..0876f3273c 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -712,7 +712,7 @@ func Routes() *web.Route {
 			m.Group("/{username}/{reponame}", func() {
 				m.Combo("").Get(reqAnyRepoReader(), repo.Get).
 					Delete(reqToken(), reqOwner(), repo.Delete).
-					Patch(reqToken(), reqAdmin(), context.RepoRefForAPI, bind(api.EditRepoOption{}), repo.Edit)
+					Patch(reqToken(), reqAdmin(), bind(api.EditRepoOption{}), repo.Edit)
 				m.Post("/transfer", reqOwner(), bind(api.TransferRepoOption{}), repo.Transfer)
 				m.Combo("/notifications").
 					Get(reqToken(), notify.ListRepoNotifications).
diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go
index c422feb043..d8600c0fcd 100644
--- a/routers/api/v1/repo/repo.go
+++ b/routers/api/v1/repo/repo.go
@@ -578,7 +578,7 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err
 		repo.IsTemplate = *opts.Template
 	}
 
-	if ctx.Repo.GitRepo == nil {
+	if ctx.Repo.GitRepo == nil && !repo.IsEmpty {
 		var err error
 		ctx.Repo.GitRepo, err = git.OpenRepository(ctx.Repo.Repository.RepoPath())
 		if err != nil {
@@ -589,13 +589,13 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err
 	}
 
 	// Default branch only updated if changed and exist or the repository is empty
-	if opts.DefaultBranch != nil &&
-		repo.DefaultBranch != *opts.DefaultBranch &&
-		(ctx.Repo.Repository.IsEmpty || ctx.Repo.GitRepo.IsBranchExist(*opts.DefaultBranch)) {
-		if err := ctx.Repo.GitRepo.SetDefaultBranch(*opts.DefaultBranch); err != nil {
-			if !git.IsErrUnsupportedVersion(err) {
-				ctx.Error(http.StatusInternalServerError, "SetDefaultBranch", err)
-				return err
+	if opts.DefaultBranch != nil && repo.DefaultBranch != *opts.DefaultBranch && (repo.IsEmpty || ctx.Repo.GitRepo.IsBranchExist(*opts.DefaultBranch)) {
+		if !repo.IsEmpty {
+			if err := ctx.Repo.GitRepo.SetDefaultBranch(*opts.DefaultBranch); err != nil {
+				if !git.IsErrUnsupportedVersion(err) {
+					ctx.Error(http.StatusInternalServerError, "SetDefaultBranch", err)
+					return err
+				}
 			}
 		}
 		repo.DefaultBranch = *opts.DefaultBranch