1
0
Просмотр исходного кода

Add embedded PostgreSQL support via --embedded-postgres flag

Co-authored-by: unknwon <2946214+unknwon@users.noreply.github.com>
copilot-swe-agent[bot] 4 дней назад
Родитель
Сommit
4616bd64dd
4 измененных файлов с 119 добавлено и 1 удалено
  1. 17 0
      cmd/gogs/web.go
  2. 3 1
      go.mod
  3. 6 0
      go.sum
  4. 93 0
      internal/embeddedpg/embeddedpg.go

+ 17 - 0
cmd/gogs/web.go

@@ -30,6 +30,7 @@ import (
 	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/database"
+	"gogs.io/gogs/internal/embeddedpg"
 	"gogs.io/gogs/internal/form"
 	"gogs.io/gogs/internal/osutil"
 	"gogs.io/gogs/internal/route"
@@ -54,6 +55,7 @@ and it takes care of all the other things for you`,
 	Flags: []cli.Flag{
 		stringFlag("port, p", "3000", "Temporary port number to prevent conflict"),
 		stringFlag("config, c", "", "Custom configuration file path"),
+		boolFlag("embedded-postgres", "Use embedded PostgreSQL database"),
 	},
 }
 
@@ -160,6 +162,21 @@ func newMacaron() *macaron.Macaron {
 }
 
 func runWeb(c *cli.Context) error {
+	var localPg *embeddedpg.LocalPostgres
+	
+	if c.Bool("embedded-postgres") {
+		localPg = embeddedpg.Initialize(conf.WorkDir())
+		if err := localPg.Launch(); err != nil {
+			log.Fatal("Failed to launch embedded postgres: %v", err)
+		}
+		defer func() {
+			if err := localPg.Shutdown(); err != nil {
+				log.Error("Failed to shutdown embedded postgres: %v", err)
+			}
+		}()
+		localPg.ConfigureGlobalDatabase()
+	}
+	
 	err := route.GlobalInit(c.String("config"))
 	if err != nil {
 		log.Fatal("Failed to initialize application: %v", err)

+ 3 - 1
go.mod

@@ -83,6 +83,7 @@ require (
 	github.com/djherbis/nio/v3 v3.0.1 // indirect
 	github.com/dustin/go-humanize v1.0.1 // indirect
 	github.com/fatih/color v1.18.0 // indirect
+	github.com/fergusstrange/embedded-postgres v1.33.0 // indirect
 	github.com/getsentry/sentry-go v0.27.0 // indirect
 	github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
 	github.com/go-logr/logr v1.2.3 // indirect
@@ -107,7 +108,7 @@ require (
 	github.com/klauspost/compress v1.18.0 // indirect
 	github.com/kr/pretty v0.3.1 // indirect
 	github.com/kr/text v0.2.0 // indirect
-	github.com/lib/pq v1.10.2 // indirect
+	github.com/lib/pq v1.10.9 // indirect
 	github.com/mattn/go-colorable v0.1.14 // indirect
 	github.com/mattn/go-isatty v0.0.20 // indirect
 	github.com/mattn/go-runewidth v0.0.19 // indirect
@@ -131,6 +132,7 @@ require (
 	github.com/russross/blackfriday/v2 v2.1.0 // indirect
 	github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca // indirect
 	github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
+	github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
 	go.bobheadxi.dev/streamline v1.2.1 // indirect
 	go.opentelemetry.io/otel v1.11.0 // indirect
 	go.opentelemetry.io/otel/trace v1.11.0 // indirect

+ 6 - 0
go.sum

@@ -91,6 +91,8 @@ github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaB
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
 github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
+github.com/fergusstrange/embedded-postgres v1.33.0 h1:ka8vmRpm4IDsES7NPXQ/NThAp1fc/f+crcXYjCW7wK0=
+github.com/fergusstrange/embedded-postgres v1.33.0/go.mod h1:w0YvnCgf19o6tskInrOOACtnqfVlOvluz3hlNLY7tRk=
 github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
 github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@@ -290,6 +292,8 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
 github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
+github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de/go.mod h1:3q8WtuPQsoRbatJuy3nvq/hRSvuBJrHHr+ybPPiNvHQ=
 github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af/go.mod h1:Cqz6pqow14VObJ7peltM+2n3PWOz7yTrfUuGbVFkzN0=
 github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
@@ -456,6 +460,8 @@ github.com/unknwon/paginater v0.0.0-20170405233947-45e5d631308e h1:Qf3QQl/zmEbWD
 github.com/unknwon/paginater v0.0.0-20170405233947-45e5d631308e/go.mod h1:TBwoao3Q4Eb/cp+dHbXDfRTrZSsj/k7kLr2j1oWRWC0=
 github.com/urfave/cli v1.22.17 h1:SYzXoiPfQjHBbkYxbew5prZHS1TOLT3ierW8SYLqtVQ=
 github.com/urfave/cli v1.22.17/go.mod h1:b0ht0aqgH/6pBYzzxURyrM4xXNgsoT/n2ZzwQiEhNVo=
+github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
+github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=

+ 93 - 0
internal/embeddedpg/embeddedpg.go

@@ -0,0 +1,93 @@
+package embeddedpg
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+	"time"
+
+	"github.com/cockroachdb/errors"
+	embpg "github.com/fergusstrange/embedded-postgres"
+	log "unknwon.dev/clog/v2"
+
+	"gogs.io/gogs/internal/conf"
+)
+
+// LocalPostgres wraps embedded PostgreSQL server functionality.
+type LocalPostgres struct {
+	srv      *embpg.EmbeddedPostgres
+	baseDir  string
+	tcpPort  uint32
+	database string
+	user     string
+	pass     string
+}
+
+// Initialize creates a LocalPostgres with default settings based on workDir.
+func Initialize(workDir string) *LocalPostgres {
+	storageBase := filepath.Join(workDir, "data", "local-postgres")
+	return &LocalPostgres{
+		baseDir:  storageBase,
+		tcpPort:  15432,
+		database: "gogs",
+		user:     "gogs",
+		pass:     "gogs",
+	}
+}
+
+// Launch starts the embedded PostgreSQL server and blocks until ready.
+func (pg *LocalPostgres) Launch() error {
+	log.Info("Launching local PostgreSQL server...")
+
+	if err := os.MkdirAll(pg.baseDir, 0700); err != nil {
+		return errors.Wrap(err, "mkdir local postgres base")
+	}
+
+	opts := embpg.DefaultConfig().
+		Username(pg.user).
+		Password(pg.pass).
+		Database(pg.database).
+		Port(pg.tcpPort).
+		DataPath(pg.baseDir).
+		RuntimePath(filepath.Join(pg.baseDir, "rt")).
+		BinariesPath(filepath.Join(pg.baseDir, "bin")).
+		CachePath(filepath.Join(pg.baseDir, "dl")).
+		StartTimeout(45 * time.Second).
+		Logger(os.Stderr)
+
+	pg.srv = embpg.NewDatabase(opts)
+
+	if err := pg.srv.Start(); err != nil {
+		return errors.Wrap(err, "launch embedded pg")
+	}
+
+	log.Info("Local PostgreSQL ready on port %d", pg.tcpPort)
+	return nil
+}
+
+// Shutdown stops the embedded PostgreSQL server gracefully.
+func (pg *LocalPostgres) Shutdown() error {
+	if pg.srv == nil {
+		return nil
+	}
+
+	log.Info("Shutting down local PostgreSQL...")
+	if err := pg.srv.Stop(); err != nil {
+		return errors.Wrap(err, "shutdown embedded pg")
+	}
+
+	log.Info("Local PostgreSQL shutdown complete")
+	return nil
+}
+
+// ConfigureGlobalDatabase modifies global conf.Database to point to this instance.
+func (pg *LocalPostgres) ConfigureGlobalDatabase() {
+	conf.Database.Type = "postgres"
+	conf.Database.Host = fmt.Sprintf("localhost:%d", pg.tcpPort)
+	conf.Database.Name = pg.database
+	conf.Database.User = pg.user
+	conf.Database.Password = pg.pass
+	conf.Database.SSLMode = "disable"
+
+	log.Trace("Global database configured for local PostgreSQL")
+}