Skip to content

Commit

Permalink
zed: Default app data location
Browse files Browse the repository at this point in the history
If no lake location is specified, zed will use a per-os default
location. Also if the default location is used, zed will first check if
there's a service on 9867 and opt to connect to that instead of
operating locally.
  • Loading branch information
mattnibs committed Oct 2, 2023
1 parent 89ef807 commit c6f9a57
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 20 deletions.
36 changes: 36 additions & 0 deletions cli/lakeflags/datadir.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package lakeflags

import (
"os"
"path/filepath"
"runtime"
)

var defaultDataDir string

func init() {
defaultDataDir = getDefaultDataDir()
}

// getDefaultDataDir returns the default data directory for the current user.
// Derived from https://github.com/btcsuite/btcd/blob/master/btcutil/appdata.go
func getDefaultDataDir() string {
// Resolve the XDG data home directory if set.
if xdgDataHome := os.Getenv("XDG_DATA_HOME"); xdgDataHome != "" {
return filepath.Join(xdgDataHome, "zed")
}
if runtime.GOOS == "windows" {
if appData := os.Getenv("LOCALAPPDATA"); appData != "" {
return filepath.Join(appData, "zed")
}
}
if homeDir, _ := os.UserHomeDir(); homeDir != "" {
// Follow the XDG spec which states:
// If $XDG_DATA_HOME is either not set or empty, a default equal to
// $HOME/.local/share should be used.
return filepath.Join(homeDir, ".local", "share", "zed")
}
// Return an empty string which will cause an error if a default data
// directory cannot be found.
return ""
}
37 changes: 27 additions & 10 deletions cli/lakeflags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,8 @@ var ErrNoHEAD = errors.New("HEAD not specified: indicate with -use or run the \"

type Flags struct {
ConfigDir string
// LakeSpecified is set to true if the lake is explicitly set via either
// command line flag or environment variable.
LakeSpecified bool
Lake string
Quiet bool
Lake string
Quiet bool
}

func (l *Flags) SetFlags(fs *flag.FlagSet) {
Expand All @@ -35,20 +32,19 @@ func (l *Flags) SetFlags(fs *flag.FlagSet) {
dir = filepath.Join(dir, ".zed")
}
fs.StringVar(&l.ConfigDir, "configdir", dir, "configuration and credentials directory")
l.Lake = "http://localhost:9867"
if s, ok := os.LookupEnv("ZED_LAKE"); ok {
l.Lake = strings.TrimRight(s, "/")
l.LakeSpecified = true
} else {
l.Lake = defaultDataDir
}
fs.Func("lake", fmt.Sprintf("lake location (env ZED_LAKE) (default %s)", l.Lake), func(s string) error {
l.Lake = strings.TrimRight(s, "/")
l.LakeSpecified = true
return nil
})
}

func (l *Flags) Connection() (*client.Connection, error) {
uri, err := l.URI()
uri, err := l.ClientURI()
if err != nil {
return nil, err
}
Expand All @@ -63,7 +59,7 @@ func (l *Flags) Connection() (*client.Connection, error) {
}

func (l *Flags) Open(ctx context.Context) (api.Interface, error) {
uri, err := l.URI()
uri, err := l.ClientURI()
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -95,3 +91,24 @@ func (l *Flags) URI() (*storage.URI, error) {
}
return u, err
}

// ClientURI returns the URI of the lake to connect to. If the lake path is
// the defaultDataDir, it first checks if a service is running on port 9867
// and if so, uses http://localhost:9867 as the lake location.
func (l *Flags) ClientURI() (*storage.URI, error) {
u, err := l.URI()
if err != nil {
return nil, err
}
// If the lake is the defaultDataDir, first check if a service is running
// on port 9867 and if so, use this as the lake location.
if u.String() == storage.MustParseURI(defaultDataDir).String() && localServer() {
u = storage.MustParseURI("http://localhost:9867")
}
return u, nil
}

func localServer() bool {
_, err := client.NewConnection().Ping(context.Background())
return err == nil
}
9 changes: 2 additions & 7 deletions cmd/zed/serve/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,12 @@ func (c *Command) Run(args []string) error {
return err
}
defer cleanup()
if !c.LakeFlags.LakeSpecified {
c.LakeFlags.Lake = ""
}
uri, err := c.LakeFlags.URI()
if err != nil {
if c.conf.Root, err = c.LakeFlags.URI(); err != nil {
return err
}
if api.IsLakeService(uri.String()) {
if api.IsLakeService(c.conf.Root.String()) {
return errors.New("serve command available for local lakes only")
}
c.conf.Root = uri
if c.rootContentFile != "" {
f, err := fs.Open(c.rootContentFile)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion cmd/zed/use/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func (c *Command) Run(args []string) error {
return errors.New("default pool and branch unset")
}
fmt.Printf("HEAD at %s\n", head)
if u, err := c.LakeFlags.URI(); err == nil {
if u, err := c.LakeFlags.ClientURI(); err == nil {
fmt.Printf("Lake at %s\n", u)
}
return nil
Expand Down
2 changes: 1 addition & 1 deletion cmd/zed/ztests/no-lake-location.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
script: |
! zed ls -lake ''
! zed serve
! zed serve -lake ''
outputs:
- name: stderr
Expand Down
8 changes: 8 additions & 0 deletions cmd/zed/ztests/xdg-data-home.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
script: |
export XDG_DATA_HOME=path/to/lake
zed init
outputs:
- name: stdout
data: |
lake created: path/to/lake/zed
2 changes: 1 addition & 1 deletion compiler/ztests/from-error.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
script: |
! zc -C -s 'from p'
! zc -lake='' -C -s 'from p'
echo === >&2
export ZED_LAKE=test
zed init
Expand Down

0 comments on commit c6f9a57

Please sign in to comment.