Repository: amacneil/dbmate (go)

Issue:
postgres automatic peer auth
Currently, it's possible to connect to a database on localhost using a domain socket. For example:

```
$ dbmate -u "postgres:///database_name?socket=/var/run/postgresql" status
```

It'd be really nice if this was autodetected and you could just do:

```
$ dbmate -u postgres:///database_name status
```

The following works well on my machine:

```
$ psql postgres:///database_name
```

I believe that `psql` is using the `peer` authentication method on my local machine over the domain socket that postgres exposes.

Some more info:
https://www.postgresql.org/docs/current/auth-peer.html

Pull request description:
Postgres defaults to unix socket with no host
Closes #229

When there's no host given in a postgres connection url, use the unix
domain default socket. Previously, the default was a localhost TCP
connection. This default behavior is more in line with standard postgres
clients out there, like psql.

Patch:
diff --git a/pkg/dbmate/db.go b/pkg/dbmate/db.go
index 815a5cb..f64dd88 100644
--- a/pkg/dbmate/db.go
+++ b/pkg/dbmate/db.go
@@ -5,7 +5,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net/url"
 	"os"
 	"path/filepath"
@@ -226,7 +225,7 @@ func (db *DB) dumpSchema(drv Driver) error {
 	}
 
 	// write schema to file
-	return ioutil.WriteFile(db.SchemaFile, schema, 0644)
+	return os.WriteFile(db.SchemaFile, schema, 0644)
 }
 
 // ensureDir creates a directory if it does not already exist
@@ -402,7 +401,7 @@ func (db *DB) printVerbose(result sql.Result) {
 }
 
 func findMigrationFiles(dir string, re *regexp.Regexp) ([]string, error) {
-	files, err := ioutil.ReadDir(dir)
+	files, err := os.ReadDir(dir)
 	if err != nil {
 		return nil, fmt.Errorf("could not find migrations directory `%s`", dir)
 	}
diff --git a/pkg/dbmate/migration.go b/pkg/dbmate/migration.go
index 2c0f7b6..bb00018 100644
--- a/pkg/dbmate/migration.go
+++ b/pkg/dbmate/migration.go
@@ -2,7 +2,7 @@ package dbmate
 
 import (
 	"fmt"
-	"io/ioutil"
+	"os"
 	"regexp"
 	"strings"
 )
@@ -33,7 +33,7 @@ func NewMigration() Migration {
 
 // parseMigration reads a migration file and returns (up Migration, down Migration, error)
 func parseMigration(path string) (Migration, Migration, error) {
-	data, err := ioutil.ReadFile(path)
+	data, err := os.ReadFile(path)
 	if err != nil {
 		return NewMigration(), NewMigration(), err
 	}
diff --git a/pkg/driver/postgres/postgres.go b/pkg/driver/postgres/postgres.go
index 1917cb1..60b1333 100644
--- a/pkg/driver/postgres/postgres.go
+++ b/pkg/driver/postgres/postgres.go
@@ -6,6 +6,7 @@ import (
 	"fmt"
 	"io"
 	"net/url"
+	"runtime"
 	"strings"
 
 	"github.com/amacneil/dbmate/pkg/dbmate"
@@ -48,7 +49,14 @@ func connectionString(u *url.URL) string {
 
 	// default hostname
 	if hostname == "" {
-		hostname = "localhost"
+		switch runtime.GOOS {
+		case "linux":
+			query.Set("host", "/var/run/postgresql")
+		case "darwin", "freebsd", "dragonfly", "openbsd", "netbsd":
+			query.Set("host", "/tmp")
+		default:
+			hostname = "localhost"
+		}
 	}
 
 	// host param overrides url hostname


Test patch:
diff --git a/pkg/dbmate/db_test.go b/pkg/dbmate/db_test.go
index 7b50daf..d2e42e5 100644
--- a/pkg/dbmate/db_test.go
+++ b/pkg/dbmate/db_test.go
@@ -1,7 +1,6 @@
 package dbmate_test
 
 import (
-	"io/ioutil"
 	"net/url"
 	"os"
 	"path/filepath"
@@ -102,7 +101,7 @@ func TestDumpSchema(t *testing.T) {
 	db := newTestDB(t, u)
 
 	// create custom schema file directory
-	dir, err := ioutil.TempDir("", "dbmate")
+	dir, err := os.MkdirTemp("", "dbmate")
 	require.NoError(t, err)
 	defer func() {
 		err := os.RemoveAll(dir)
@@ -129,7 +128,7 @@ func TestDumpSchema(t *testing.T) {
 	require.NoError(t, err)
 
 	// verify schema
-	schema, err := ioutil.ReadFile(db.SchemaFile)
+	schema, err := os.ReadFile(db.SchemaFile)
 	require.NoError(t, err)
 	require.Contains(t, string(schema), "-- PostgreSQL database dump")
 }
@@ -140,7 +139,7 @@ func TestAutoDumpSchema(t *testing.T) {
 	db.AutoDumpSchema = true
 
 	// create custom schema file directory
-	dir, err := ioutil.TempDir("", "dbmate")
+	dir, err := os.MkdirTemp("", "dbmate")
 	require.NoError(t, err)
 	defer func() {
 		err := os.RemoveAll(dir)
@@ -163,7 +162,7 @@ func TestAutoDumpSchema(t *testing.T) {
 	require.NoError(t, err)
 
 	// verify schema
-	schema, err := ioutil.ReadFile(db.SchemaFile)
+	schema, err := os.ReadFile(db.SchemaFile)
 	require.NoError(t, err)
 	require.Contains(t, string(schema), "-- PostgreSQL database dump")
 
@@ -176,7 +175,7 @@ func TestAutoDumpSchema(t *testing.T) {
 	require.NoError(t, err)
 
 	// schema should be recreated
-	schema, err = ioutil.ReadFile(db.SchemaFile)
+	schema, err = os.ReadFile(db.SchemaFile)
 	require.NoError(t, err)
 	require.Contains(t, string(schema), "-- PostgreSQL database dump")
 }
diff --git a/pkg/driver/postgres/postgres_test.go b/pkg/driver/postgres/postgres_test.go
index f3f8793..1a49ce0 100644
--- a/pkg/driver/postgres/postgres_test.go
+++ b/pkg/driver/postgres/postgres_test.go
@@ -4,6 +4,7 @@ import (
 	"database/sql"
 	"net/url"
 	"os"
+	"runtime"
 	"testing"
 
 	"github.com/amacneil/dbmate/pkg/dbmate"
@@ -50,13 +51,24 @@ func TestGetDriver(t *testing.T) {
 	require.Equal(t, "schema_migrations", drv.migrationsTableName)
 }
 
+func defaultConnString() string {
+	switch runtime.GOOS {
+	case "linux":
+		return "postgres://:5432/foo?host=%2Fvar%2Frun%2Fpostgresql"
+	case "darwin", "freebsd", "dragonfly", "openbsd", "netbsd":
+		return "postgres://:5432/foo?host=%2Ftmp"
+	default:
+		return "postgres://localhost:5432/foo"
+	}
+}
+
 func TestConnectionString(t *testing.T) {
 	cases := []struct {
 		input    string
 		expected string
 	}{
 		// defaults
-		{"postgres:///foo", "postgres://localhost:5432/foo"},
+		{"postgres:///foo", defaultConnString()},
 		// support custom url params
 		{"postgres://bob:secret@myhost:1234/foo?bar=baz", "postgres://bob:secret@myhost:1234/foo?bar=baz"},
 		// support `host` and `port` via url params
@@ -85,11 +97,11 @@ func TestConnectionArgsForDump(t *testing.T) {
 		expected []string
 	}{
 		// defaults
-		{"postgres:///foo", []string{"postgres://localhost:5432/foo"}},
+		{"postgres:///foo", []string{defaultConnString()}},
 		// support single schema
-		{"postgres:///foo?search_path=foo", []string{"--schema", "foo", "postgres://localhost:5432/foo"}},
+		{"postgres:///foo?search_path=foo", []string{"--schema", "foo", defaultConnString()}},
 		// support multiple schemas
-		{"postgres:///foo?search_path=foo,public", []string{"--schema", "foo", "--schema", "public", "postgres://localhost:5432/foo"}},
+		{"postgres:///foo?search_path=foo,public", []string{"--schema", "foo", "--schema", "public", defaultConnString()}},
 	}
 
 	for _, c := range cases {