mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-02-04 12:46:45 +00:00
fix: automatically create parent directory of Sqlite db
This commit is contained in:
@@ -155,6 +155,12 @@ func connectDatabase() (db *gorm.DB, err error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !isMemoryDB {
|
||||||
|
if err := ensureSqliteDatabaseDir(dbPath); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Before we connect, also make sure that there's a temporary folder for SQLite to write its data
|
// Before we connect, also make sure that there's a temporary folder for SQLite to write its data
|
||||||
err = ensureSqliteTempDir(filepath.Dir(dbPath))
|
err = ensureSqliteTempDir(filepath.Dir(dbPath))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -388,6 +394,27 @@ func isSqliteInMemory(connString string) bool {
|
|||||||
return len(qs["mode"]) > 0 && qs["mode"][0] == "memory"
|
return len(qs["mode"]) > 0 && qs["mode"][0] == "memory"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensureSqliteDatabaseDir creates the parent directory for the SQLite database file if it doesn't exist yet
|
||||||
|
func ensureSqliteDatabaseDir(dbPath string) error {
|
||||||
|
dir := filepath.Dir(dbPath)
|
||||||
|
|
||||||
|
info, err := os.Stat(dir)
|
||||||
|
switch {
|
||||||
|
case err == nil:
|
||||||
|
if !info.IsDir() {
|
||||||
|
return fmt.Errorf("SQLite database directory '%s' is not a directory", dir)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
case os.IsNotExist(err):
|
||||||
|
if err := os.MkdirAll(dir, 0700); err != nil {
|
||||||
|
return fmt.Errorf("failed to create SQLite database directory '%s': %w", dir, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("failed to check SQLite database directory '%s': %w", dir, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ensureSqliteTempDir ensures that SQLite has a directory where it can write temporary files if needed
|
// ensureSqliteTempDir ensures that SQLite has a directory where it can write temporary files if needed
|
||||||
// The default directory may not be writable when using a container with a read-only root file system
|
// The default directory may not be writable when using a container with a read-only root file system
|
||||||
// See: https://www.sqlite.org/tempfiles.html
|
// See: https://www.sqlite.org/tempfiles.html
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package bootstrap
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -84,6 +86,29 @@ func TestIsSqliteInMemory(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEnsureSqliteDatabaseDir(t *testing.T) {
|
||||||
|
t.Run("creates missing directory", func(t *testing.T) {
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
dbPath := filepath.Join(tempDir, "nested", "pocket-id.db")
|
||||||
|
|
||||||
|
err := ensureSqliteDatabaseDir(dbPath)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
info, err := os.Stat(filepath.Dir(dbPath))
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.True(t, info.IsDir())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("fails when parent is file", func(t *testing.T) {
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
filePath := filepath.Join(tempDir, "file.txt")
|
||||||
|
require.NoError(t, os.WriteFile(filePath, []byte("test"), 0o600))
|
||||||
|
|
||||||
|
err := ensureSqliteDatabaseDir(filepath.Join(filePath, "data.db"))
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestConvertSqlitePragmaArgs(t *testing.T) {
|
func TestConvertSqlitePragmaArgs(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
|||||||
Reference in New Issue
Block a user