diff --git a/db.go b/db.go index 1b777b4..9aca982 100644 --- a/db.go +++ b/db.go @@ -18,22 +18,15 @@ const ( cardBucket string = "card" ) -// openDatabase opens the database, at a given path, for reading and writing. If the file does not exist it will be created. -// For linux, the default location of the database file is $XDG_DATA_HOME/pelican/pelican.db. If the XDG_DATA_HOME environment -// variable is not set then it will default to $HOME/.local/share/pelican/pelican.db. -// For all other operating systems the default location is $HOME/.pelican/pelican.db. -func openDatabase(path string) (*bolt.DB, error) { - opts := bolt.Options{ - Timeout: 1 * time.Second, - } +func mkDataDir(dir string) error { + return os.MkdirAll(dir, 0700) +} +// TODO: Needs unit testing and documentation +func dbPath(path string) (string, error) { if len(path) > 0 { - db, err := bolt.Open(path, 0600, &opts) - if err != nil { - return nil, fmt.Errorf("unable to open database at %s, %w", path, err) - } - - return db, nil + filepath.Dir(path) + return path, mkDataDir(filepath.Dir(path)) } dbFilename := "pelican.db" @@ -55,11 +48,24 @@ func openDatabase(path string) (*bolt.DB, error) { } if err := os.MkdirAll(dataDir, 0700); err != nil { - return nil, fmt.Errorf("unable to make directory %s, %w", dataDir, err) + return "", fmt.Errorf("unable to make directory %s, %w", dataDir, err) } path = filepath.Join(dataDir, dbFilename) + return path, mkDataDir(dataDir) + +} + +// openDatabase opens the database, at a given path, for reading and writing. If the file does not exist it will be created. +// For linux, the default location of the database file is $XDG_DATA_HOME/pelican/pelican.db. If the XDG_DATA_HOME environment +// variable is not set then it will default to $HOME/.local/share/pelican/pelican.db. +// For all other operating systems the default location is $HOME/.pelican/pelican.db. +func openDatabase(path string) (*bolt.DB, error) { + opts := bolt.Options{ + Timeout: 1 * time.Second, + } + db, err := bolt.Open(path, 0600, &opts) if err != nil { return nil, fmt.Errorf("unable to open database at %s, %w", path, err) diff --git a/db_test.go b/db_test.go index 00dd1b9..db12cf1 100644 --- a/db_test.go +++ b/db_test.go @@ -3,12 +3,62 @@ package main import ( "fmt" "os" + "path/filepath" "reflect" + "runtime" "testing" bolt "go.etcd.io/bbolt" ) +func TestDbCustomPath(t *testing.T) { + cwd, err := os.Getwd() + if err != nil { + t.Fatalf("An error occurred whilst getting the current directory, %s", err) + } + + tempDataDir := filepath.Join(cwd, "test/temp_data_dir") + defer os.RemoveAll(tempDataDir) + + path := filepath.Join(tempDataDir + "/test.db") + + got, err := dbPath(path) + if err != nil { + t.Fatalf("An error occurred whilst executing `dbPath`, %s", err) + } + + if got != path { + t.Errorf("Got unexpected database path: want %s, got %s", path, got) + } else { + t.Logf("Got expected database path: got %s", got) + } +} + +// TODO: Finish testing +func TestDbDefaultPath(t *testing.T) { + var wantPath string + + cwd, err := os.Getwd() + if err != nil { + t.Fatalf("An error occurred whilst getting the current directory, %s", err) + } + + testXdgDataHome := fmt.Sprintf("%s/%s/%s/%s", cwd, "test", ".local", "data") + defer os.RemoveAll(testXdgDataHome) + + if err := os.Setenv("XDG_DATA_HOME", testXdgDataHome); err != nil { + t.Fatalf("An error occurred whilst setting the XDG_DATA_HOME environment variable, %s", err) + } + + goos := runtime.GOOS + switch goos { + case "linux": + wantPath = filepath.Join(os.Getenv("XDG_DATA_HOME"), "pelican", "pelican.db") + default: + wantPath = filepath.Join(os.Getenv("HOME"), ".pelican", "pelican.db") + } +} + func TestEnsureBuckets(t *testing.T) { var db *bolt.DB var err error