99 lines
1.9 KiB
Go
99 lines
1.9 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
|
|
"bazil.org/fuse"
|
|
"bazil.org/fuse/fs"
|
|
)
|
|
|
|
func main() {
|
|
m := NewMain()
|
|
if err := m.Run(os.Args[1:]); err == flag.ErrHelp {
|
|
os.Exit(1)
|
|
} else if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
type Main struct {
|
|
logger *log.Logger
|
|
|
|
SourcePath string
|
|
MountPath string
|
|
}
|
|
|
|
func NewMain() *Main {
|
|
return &Main{
|
|
logger: log.New(ioutil.Discard, "", log.LstdFlags),
|
|
}
|
|
}
|
|
|
|
func (m *Main) Run(args []string) (err error) {
|
|
flagSet := flag.NewFlagSet("litestream", flag.ContinueOnError)
|
|
verbose := flagSet.Bool("v", false, "verbose")
|
|
flagSet.Usage = m.usage
|
|
if err := flagSet.Parse(args); err != nil {
|
|
return err
|
|
}
|
|
if m.SourcePath = flagSet.Arg(0); m.SourcePath == "" {
|
|
return errors.New("source path required")
|
|
} else if m.MountPath = flagSet.Arg(1); m.MountPath == "" {
|
|
return errors.New("mount path required")
|
|
}
|
|
|
|
// Setup logging, if verbose specified.
|
|
if *verbose {
|
|
m.logger = log.New(os.Stderr, "", log.LstdFlags)
|
|
}
|
|
|
|
// Mount FUSE filesystem.
|
|
conn, err := fuse.Mount(m.MountPath, fuse.FSName("litestream"), fuse.Subtype("litestreamfs"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer fuse.Unmount(m.MountPath)
|
|
defer conn.Close()
|
|
|
|
m.logger.Printf("mounted")
|
|
|
|
s := fs.New(conn, &fs.Config{
|
|
Debug: debug,
|
|
})
|
|
return s.Serve(&FS{SourcePath: m.SourcePath})
|
|
}
|
|
|
|
func (m *Main) usage() {
|
|
fmt.Println(`
|
|
Litestream is a FUSE file system that automatically replicates SQLite databases.
|
|
|
|
Usage:
|
|
|
|
litestream [arguments] source_dir mount_dir
|
|
|
|
Arguments:
|
|
|
|
-v
|
|
Enable verbose logging.
|
|
|
|
`[1:])
|
|
}
|
|
|
|
// debug is a function that can be used for fs.Config.Debug.
|
|
// It marshals the msg to JSON and prints to the log.
|
|
func debug(msg interface{}) {
|
|
buf, err := json.Marshal(msg)
|
|
if err != nil {
|
|
println("debug: marshal error: %v", err)
|
|
return
|
|
}
|
|
log.Print("DEBUG ", string(buf))
|
|
}
|