From 3eacbfead9b2e8bdbedd88d37af801b6139e1411 Mon Sep 17 00:00:00 2001
From: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Date: Thu, 20 Feb 2025 22:26:30 +0000
Subject: [PATCH] [v10.0/forgejo] fix: return 404 for empty repositories
 (#7014)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7003

Some endpoints (`/api/v1/repos/*/*/raw`, `/api/v1/repos/*/*/media`, ...;
anything that uses both `context.ReferencesGitRepo()` and
`context.RepoRefForAPI` really) returned a 500 when the repository was
completely empty. This resulted in some confusion in
https://github.com/datalad/datalad-usage-dashboard/issues/47 because the
same request for a non-existent file in a repository could sometimes
generate a 404 and sometimes a 500, depending on if the git repository
is initialized at all or not.

Returning a 404 seems more appropriate here, since this isn't an
unexpected internal error, but just another way of not finding the
requested data.

Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7014
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
---
 services/context/api.go              |  5 +++++
 tests/integration/empty_repo_test.go | 21 +++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/services/context/api.go b/services/context/api.go
index 396ceb520f..3289727425 100644
--- a/services/context/api.go
+++ b/services/context/api.go
@@ -353,6 +353,11 @@ func RepoRefForAPI(next http.Handler) http.Handler {
 	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
 		ctx := GetAPIContext(req)
 
+		if ctx.Repo.Repository.IsEmpty {
+			ctx.NotFound(fmt.Errorf("repository is empty"))
+			return
+		}
+
 		if ctx.Repo.GitRepo == nil {
 			ctx.InternalServerError(fmt.Errorf("no open git repo"))
 			return
diff --git a/tests/integration/empty_repo_test.go b/tests/integration/empty_repo_test.go
index 4122c78ec2..637de7d5c7 100644
--- a/tests/integration/empty_repo_test.go
+++ b/tests/integration/empty_repo_test.go
@@ -136,3 +136,24 @@ func TestEmptyRepoAddFileByAPI(t *testing.T) {
 	DecodeJSON(t, resp, &apiRepo)
 	assert.Equal(t, "new_branch", apiRepo.DefaultBranch)
 }
+
+func TestEmptyRepoAPIRequestsReturn404(t *testing.T) {
+	defer tests.PrepareTestEnv(t)()
+
+	session := loginUser(t, "user30")
+	token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
+
+	t.Run("Raw", func(t *testing.T) {
+		defer tests.PrintCurrentTest(t)()
+
+		req := NewRequest(t, "GET", "/api/v1/repos/user30/empty/raw/main/something").AddTokenAuth(token)
+		_ = session.MakeRequest(t, req, http.StatusNotFound)
+	})
+
+	t.Run("Media", func(t *testing.T) {
+		defer tests.PrintCurrentTest(t)()
+
+		req := NewRequest(t, "GET", "/api/v1/repos/user30/empty/media/main/something").AddTokenAuth(token)
+		_ = session.MakeRequest(t, req, http.StatusNotFound)
+	})
+}