From 67881ae99abc673954d56436730af313c93ee48f Mon Sep 17 00:00:00 2001
From: Jason Song <i@wolfogre.com>
Date: Wed, 30 Nov 2022 21:39:02 +0800
Subject: [PATCH] Skip initing disabled storages (#21985)

If `Attachment` or `Packages` are disabled, we don't have to init the
storages for them.
---
 modules/storage/helper.go      | 32 +++++++++++++++++++++
 modules/storage/helper_test.go | 50 ++++++++++++++++++++++++++++++++
 modules/storage/storage.go     | 52 +++++++++++++++++-----------------
 3 files changed, 108 insertions(+), 26 deletions(-)
 create mode 100644 modules/storage/helper_test.go

diff --git a/modules/storage/helper.go b/modules/storage/helper.go
index 5aaa2a9e64..1ab99d98b3 100644
--- a/modules/storage/helper.go
+++ b/modules/storage/helper.go
@@ -4,6 +4,10 @@
 package storage
 
 import (
+	"fmt"
+	"io"
+	"net/url"
+	"os"
 	"reflect"
 
 	"code.gitea.io/gitea/modules/json"
@@ -61,3 +65,31 @@ func toConfig(exemplar, cfg interface{}) (interface{}, error) {
 	}
 	return newVal.Elem().Interface(), nil
 }
+
+var uninitializedStorage = discardStorage("uninitialized storage")
+
+type discardStorage string
+
+func (s discardStorage) Open(_ string) (Object, error) {
+	return nil, fmt.Errorf("%s", s)
+}
+
+func (s discardStorage) Save(_ string, _ io.Reader, _ int64) (int64, error) {
+	return 0, fmt.Errorf("%s", s)
+}
+
+func (s discardStorage) Stat(_ string) (os.FileInfo, error) {
+	return nil, fmt.Errorf("%s", s)
+}
+
+func (s discardStorage) Delete(_ string) error {
+	return fmt.Errorf("%s", s)
+}
+
+func (s discardStorage) URL(_, _ string) (*url.URL, error) {
+	return nil, fmt.Errorf("%s", s)
+}
+
+func (s discardStorage) IterateObjects(_ func(string, Object) error) error {
+	return fmt.Errorf("%s", s)
+}
diff --git a/modules/storage/helper_test.go b/modules/storage/helper_test.go
new file mode 100644
index 0000000000..7d74671c54
--- /dev/null
+++ b/modules/storage/helper_test.go
@@ -0,0 +1,50 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package storage
+
+import (
+	"bytes"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func Test_discardStorage(t *testing.T) {
+	tests := []discardStorage{
+		uninitializedStorage,
+		discardStorage("empty"),
+	}
+	for _, tt := range tests {
+		t.Run(string(tt), func(t *testing.T) {
+			{
+				got, err := tt.Open("path")
+				assert.Nil(t, got)
+				assert.Error(t, err, string(tt))
+			}
+			{
+				got, err := tt.Save("path", bytes.NewReader([]byte{0}), 1)
+				assert.Equal(t, int64(0), got)
+				assert.Error(t, err, string(tt))
+			}
+			{
+				got, err := tt.Stat("path")
+				assert.Nil(t, got)
+				assert.Error(t, err, string(tt))
+			}
+			{
+				err := tt.Delete("path")
+				assert.Error(t, err, string(tt))
+			}
+			{
+				got, err := tt.URL("path", "name")
+				assert.Nil(t, got)
+				assert.Errorf(t, err, string(tt))
+			}
+			{
+				err := tt.IterateObjects(func(_ string, _ Object) error { return nil })
+				assert.Error(t, err, string(tt))
+			}
+		})
+	}
+}
diff --git a/modules/storage/storage.go b/modules/storage/storage.go
index a7d3b9ce1f..35f1527172 100644
--- a/modules/storage/storage.go
+++ b/modules/storage/storage.go
@@ -110,46 +110,38 @@ func SaveFrom(objStorage ObjectStorage, p string, callback func(w io.Writer) err
 
 var (
 	// Attachments represents attachments storage
-	Attachments ObjectStorage
+	Attachments ObjectStorage = uninitializedStorage
 
 	// LFS represents lfs storage
-	LFS ObjectStorage
+	LFS ObjectStorage = uninitializedStorage
 
 	// Avatars represents user avatars storage
-	Avatars ObjectStorage
+	Avatars ObjectStorage = uninitializedStorage
 	// RepoAvatars represents repository avatars storage
-	RepoAvatars ObjectStorage
+	RepoAvatars ObjectStorage = uninitializedStorage
 
 	// RepoArchives represents repository archives storage
-	RepoArchives ObjectStorage
+	RepoArchives ObjectStorage = uninitializedStorage
 
 	// Packages represents packages storage
-	Packages ObjectStorage
+	Packages ObjectStorage = uninitializedStorage
 )
 
 // Init init the stoarge
 func Init() error {
-	if err := initAttachments(); err != nil {
-		return err
+	for _, f := range []func() error{
+		initAttachments,
+		initAvatars,
+		initRepoAvatars,
+		initLFS,
+		initRepoArchives,
+		initPackages,
+	} {
+		if err := f(); err != nil {
+			return err
+		}
 	}
-
-	if err := initAvatars(); err != nil {
-		return err
-	}
-
-	if err := initRepoAvatars(); err != nil {
-		return err
-	}
-
-	if err := initLFS(); err != nil {
-		return err
-	}
-
-	if err := initRepoArchives(); err != nil {
-		return err
-	}
-
-	return initPackages()
+	return nil
 }
 
 // NewStorage takes a storage type and some config and returns an ObjectStorage or an error
@@ -172,6 +164,10 @@ func initAvatars() (err error) {
 }
 
 func initAttachments() (err error) {
+	if !setting.Attachment.Enabled {
+		Attachments = discardStorage("Attachment isn't enabled")
+		return nil
+	}
 	log.Info("Initialising Attachment storage with type: %s", setting.Attachment.Storage.Type)
 	Attachments, err = NewStorage(setting.Attachment.Storage.Type, &setting.Attachment.Storage)
 	return err
@@ -196,6 +192,10 @@ func initRepoArchives() (err error) {
 }
 
 func initPackages() (err error) {
+	if !setting.Packages.Enabled {
+		Packages = discardStorage("Packages isn't enabled")
+		return nil
+	}
 	log.Info("Initialising Packages storage with type: %s", setting.Packages.Storage.Type)
 	Packages, err = NewStorage(setting.Packages.Storage.Type, &setting.Packages.Storage)
 	return err