mirror of
https://github.com/dolthub/dolt.git
synced 2026-02-08 18:58:47 -06:00
noms as one command line application, with version and help (#1874)
This commit is contained in:
1
cmd/noms-diff/.gitignore
vendored
1
cmd/noms-diff/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
noms-diff
|
||||
@@ -1,72 +0,0 @@
|
||||
// Copyright 2016 Attic Labs, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, version 2.0:
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/attic-labs/noms/cmd/noms-diff/diff"
|
||||
"github.com/attic-labs/noms/go/d"
|
||||
"github.com/attic-labs/noms/go/spec"
|
||||
"github.com/attic-labs/noms/go/util/outputpager"
|
||||
)
|
||||
|
||||
const (
|
||||
addPrefix = "+ "
|
||||
subPrefix = "- "
|
||||
)
|
||||
|
||||
var (
|
||||
showHelp = flag.Bool("help", false, "show help text")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintln(os.Stderr, "Shows the difference between two objects\n")
|
||||
fmt.Fprintln(os.Stderr, "Usage: noms diff <object1> <object2>\n")
|
||||
flag.PrintDefaults()
|
||||
fmt.Fprintf(os.Stderr, "\nSee \"Spelling Objects\" at https://github.com/attic-labs/noms/blob/master/doc/spelling.md for details on the object argument.\n\n")
|
||||
}
|
||||
|
||||
flag.Parse()
|
||||
if *showHelp {
|
||||
flag.Usage()
|
||||
return
|
||||
}
|
||||
|
||||
if len(flag.Args()) != 2 {
|
||||
d.CheckErrorNoUsage(errors.New("Expected exactly two arguments"))
|
||||
}
|
||||
|
||||
db1, value1, err := spec.GetPath(flag.Arg(0))
|
||||
d.CheckErrorNoUsage(err)
|
||||
if value1 == nil {
|
||||
d.CheckErrorNoUsage(fmt.Errorf("Object not found: %s", flag.Arg(0)))
|
||||
}
|
||||
defer db1.Close()
|
||||
|
||||
db2, value2, err := spec.GetPath(flag.Arg(1))
|
||||
d.CheckErrorNoUsage(err)
|
||||
if value2 == nil {
|
||||
d.CheckErrorNoUsage(fmt.Errorf("Object not found: %s", flag.Arg(1)))
|
||||
}
|
||||
defer db2.Close()
|
||||
|
||||
waitChan := outputpager.PageOutput(!*outputpager.NoPager)
|
||||
|
||||
w := bufio.NewWriter(os.Stdout)
|
||||
diff.Diff(w, value1, value2)
|
||||
fmt.Fprintf(w, "\n")
|
||||
w.Flush()
|
||||
|
||||
if waitChan != nil {
|
||||
os.Stdout.Close()
|
||||
<-waitChan
|
||||
}
|
||||
}
|
||||
1
cmd/noms-ds/.gitignore
vendored
1
cmd/noms-ds/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
noms-ds
|
||||
1
cmd/noms-log/.gitignore
vendored
1
cmd/noms-log/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
noms-log
|
||||
1
cmd/noms-serve/.gitignore
vendored
1
cmd/noms-serve/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
noms-serve
|
||||
@@ -1,57 +0,0 @@
|
||||
// Copyright 2016 Attic Labs, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, version 2.0:
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/attic-labs/noms/go/d"
|
||||
"github.com/attic-labs/noms/go/datas"
|
||||
"github.com/attic-labs/noms/go/spec"
|
||||
"github.com/attic-labs/noms/go/util/profile"
|
||||
)
|
||||
|
||||
var (
|
||||
port = flag.Int("port", 8000, "")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintf(os.Stderr, "Serves a Noms database over HTTP\n\n")
|
||||
fmt.Fprintf(os.Stderr, "Usage: noms serve <database>\n")
|
||||
flag.PrintDefaults()
|
||||
fmt.Fprintf(os.Stderr, "\nFor detailed information on spelling databases, see: at https://github.com/attic-labs/noms/blob/master/doc/spelling.md.\n\n")
|
||||
}
|
||||
|
||||
spec.RegisterDatabaseFlags()
|
||||
flag.Parse()
|
||||
|
||||
if len(flag.Args()) != 1 {
|
||||
flag.Usage()
|
||||
return
|
||||
}
|
||||
|
||||
cs, err := spec.GetChunkStore(flag.Arg(0))
|
||||
d.CheckError(err)
|
||||
server := datas.NewRemoteDatabaseServer(cs, *port)
|
||||
|
||||
// Shutdown server gracefully so that profile may be written
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt)
|
||||
signal.Notify(c, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-c
|
||||
server.Stop()
|
||||
}()
|
||||
|
||||
d.Try(func() {
|
||||
defer profile.MaybeStartProfile().Stop()
|
||||
server.Run()
|
||||
})
|
||||
}
|
||||
1
cmd/noms-show/.gitignore
vendored
1
cmd/noms-show/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
noms-show
|
||||
@@ -1,62 +0,0 @@
|
||||
// Copyright 2016 Attic Labs, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, version 2.0:
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/attic-labs/noms/go/d"
|
||||
"github.com/attic-labs/noms/go/spec"
|
||||
"github.com/attic-labs/noms/go/types"
|
||||
"github.com/attic-labs/noms/go/util/outputpager"
|
||||
)
|
||||
|
||||
var (
|
||||
showHelp = flag.Bool("help", false, "show help text")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintln(os.Stderr, "Shows a serialization of a Noms object\n")
|
||||
fmt.Fprintln(os.Stderr, "Usage: noms show <object>\n")
|
||||
flag.PrintDefaults()
|
||||
fmt.Fprintf(os.Stderr, "\nSee \"Spelling Objects\" at https://github.com/attic-labs/noms/blob/master/doc/spelling.md for details on the object argument.\n\n")
|
||||
}
|
||||
|
||||
flag.Parse()
|
||||
if *showHelp {
|
||||
flag.Usage()
|
||||
return
|
||||
}
|
||||
|
||||
if len(flag.Args()) != 1 {
|
||||
d.CheckErrorNoUsage(errors.New("expected exactly one argument"))
|
||||
}
|
||||
|
||||
database, value, err := spec.GetPath(flag.Arg(0))
|
||||
d.CheckErrorNoUsage(err)
|
||||
|
||||
if value == nil {
|
||||
fmt.Fprintf(os.Stderr, "Object not found: %s\n", flag.Arg(0))
|
||||
return
|
||||
}
|
||||
|
||||
waitChan := outputpager.PageOutput(!*outputpager.NoPager)
|
||||
|
||||
w := bufio.NewWriter(os.Stdout)
|
||||
types.WriteEncodedValueWithTags(w, value)
|
||||
fmt.Fprintf(w, "\n")
|
||||
w.Flush()
|
||||
database.Close()
|
||||
|
||||
if waitChan != nil {
|
||||
os.Stdout.Close()
|
||||
<-waitChan
|
||||
}
|
||||
}
|
||||
1
cmd/noms-sync/.gitignore
vendored
1
cmd/noms-sync/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
noms-sync
|
||||
@@ -1,58 +0,0 @@
|
||||
// Copyright 2016 Attic Labs, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, version 2.0:
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/attic-labs/noms/go/d"
|
||||
"github.com/attic-labs/noms/go/spec"
|
||||
"github.com/attic-labs/noms/go/types"
|
||||
"github.com/attic-labs/noms/go/util/profile"
|
||||
)
|
||||
|
||||
var (
|
||||
p = flag.Uint("p", 512, "parallelism")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintf(os.Stderr, "Moves datasets between or within databases\n\n")
|
||||
fmt.Fprintf(os.Stderr, "noms sync [options] <source-object> <dest-dataset>\n\n")
|
||||
flag.PrintDefaults()
|
||||
fmt.Fprintf(os.Stderr, "\nFor detailed information on spelling objects and datasets, see: at https://github.com/attic-labs/noms/blob/master/doc/spelling.md.\n\n")
|
||||
}
|
||||
|
||||
spec.RegisterDatabaseFlags()
|
||||
flag.Parse()
|
||||
|
||||
if flag.NArg() != 2 {
|
||||
d.CheckError(errors.New("expected a source object and destination dataset"))
|
||||
}
|
||||
|
||||
sourceStore, sourceObj, err := spec.GetPath(flag.Arg(0))
|
||||
d.CheckError(err)
|
||||
defer sourceStore.Close()
|
||||
|
||||
sinkDataset, err := spec.GetDataset(flag.Arg(1))
|
||||
d.CheckError(err)
|
||||
defer sinkDataset.Database().Close()
|
||||
|
||||
err = d.Try(func() {
|
||||
defer profile.MaybeStartProfile().Stop()
|
||||
|
||||
var err error
|
||||
sinkDataset, err = sinkDataset.Pull(sourceStore, types.NewRef(sourceObj), int(*p))
|
||||
d.PanicIfError(err)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,3 @@
|
||||
# noms-serve
|
||||
|
||||
noms-serve implements a noms database over HTTP.
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
@@ -24,6 +24,7 @@ type maxLineWriter struct {
|
||||
node LogNode
|
||||
dest io.Writer
|
||||
needsPrefix bool
|
||||
showGraph bool
|
||||
}
|
||||
|
||||
func (w *maxLineWriter) writeMax(data []byte, enforceMax bool) (byteCnt int, err error) {
|
||||
@@ -31,7 +32,7 @@ func (w *maxLineWriter) writeMax(data []byte, enforceMax bool) (byteCnt int, err
|
||||
if w.needsPrefix {
|
||||
w.needsPrefix = false
|
||||
w.numLines++
|
||||
if *showGraph {
|
||||
if w.showGraph {
|
||||
s := genGraph(w.node, w.numLines)
|
||||
_, err = w.dest.Write([]byte(s))
|
||||
}
|
||||
152
cmd/noms/noms.go
152
cmd/noms/noms.go
@@ -8,147 +8,51 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
const (
|
||||
cmdPrefix = "noms-"
|
||||
)
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: %s command [command-args]\n\n", path.Base(os.Args[0]))
|
||||
if hasDefinedFlags(flag.CommandLine) {
|
||||
fmt.Fprintf(os.Stderr, "Flags:\n\n")
|
||||
flag.PrintDefaults()
|
||||
fmt.Fprintf(os.Stderr, "\n")
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "Commands:\n\n")
|
||||
fmt.Fprintf(os.Stderr, " %s\n", strings.Join(listCmds(), "\n "))
|
||||
fmt.Fprintf(os.Stderr, "\nSee noms <command> -h for information on each available command.\n\n")
|
||||
var commands = []*nomsCommand{
|
||||
nomsDiff,
|
||||
nomsDs,
|
||||
nomsLog,
|
||||
nomsServe,
|
||||
nomsShow,
|
||||
nomsSync,
|
||||
nomsVersion,
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
|
||||
if flag.NArg() == 0 || flag.Arg(0) == "help" {
|
||||
args := flag.Args()
|
||||
if len(args) < 1 {
|
||||
usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
cmd := findCmd(flag.Arg(0))
|
||||
if cmd == "" {
|
||||
fmt.Fprintf(os.Stderr, "error: %s is not an available command\n", flag.Arg(0))
|
||||
usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
executeCmd(cmd)
|
||||
}
|
||||
|
||||
func hasDefinedFlags(fs *flag.FlagSet) (hasFlags bool) {
|
||||
fs.VisitAll(func(*flag.Flag) {
|
||||
hasFlags = true
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func findCmd(name string) (cmd string) {
|
||||
nomsName := cmdPrefix + name
|
||||
forEachDir(func(dir *os.File) (stop bool) {
|
||||
if isNomsExecutable(dir, nomsName) {
|
||||
cmd = path.Join(dir.Name(), nomsName)
|
||||
stop = true
|
||||
}
|
||||
return
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func listCmds() []string {
|
||||
cmds := []string{}
|
||||
|
||||
forEachDir(func(dir *os.File) (stop bool) {
|
||||
// dir.Readdirnames may return an error, but |names| may still contain valid files.
|
||||
names, _ := dir.Readdirnames(0)
|
||||
for _, n := range names {
|
||||
if isNomsExecutable(dir, n) {
|
||||
cmds = append(cmds, n[len(cmdPrefix):])
|
||||
}
|
||||
}
|
||||
if args[0] == "help" {
|
||||
help(args[1:])
|
||||
return
|
||||
})
|
||||
|
||||
sort.Strings(cmds)
|
||||
return cmds
|
||||
}
|
||||
|
||||
func forEachDir(cb func(dir *os.File) bool) {
|
||||
lookups := []struct {
|
||||
Env string
|
||||
Suffix string
|
||||
}{
|
||||
{"PATH", ""},
|
||||
{"GOPATH", "bin"},
|
||||
}
|
||||
|
||||
seen := map[string]bool{}
|
||||
for _, cmd := range commands {
|
||||
if cmd.Name() == args[0] {
|
||||
flags := cmd.Flags()
|
||||
flags.Usage = cmd.Usage
|
||||
|
||||
for _, lookup := range lookups {
|
||||
env := os.Getenv(lookup.Env)
|
||||
if env == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
paths := strings.Split(env, string(os.PathListSeparator))
|
||||
for _, p := range paths {
|
||||
p := path.Join(p, lookup.Suffix)
|
||||
|
||||
if seen[p] {
|
||||
continue
|
||||
flags.Parse(args[1:])
|
||||
args = flags.Args()
|
||||
if cmd.Nargs != 0 && len(args) < cmd.Nargs {
|
||||
cmd.Usage()
|
||||
}
|
||||
|
||||
seen[p] = true
|
||||
|
||||
if dir, err := os.Open(p); err == nil && cb(dir) {
|
||||
return
|
||||
exitCode := cmd.Run(args)
|
||||
if exitCode != 0 {
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func executeCmd(executable string) {
|
||||
args := flag.Args()[1:]
|
||||
if len(args) == 0 {
|
||||
args = append(args, "-help")
|
||||
}
|
||||
nomsCmd := exec.Command(executable, args...)
|
||||
nomsCmd.Stdin = os.Stdin
|
||||
nomsCmd.Stdout = os.Stdout
|
||||
nomsCmd.Stderr = os.Stderr
|
||||
|
||||
err := nomsCmd.Run()
|
||||
if err != nil {
|
||||
switch t := err.(type) {
|
||||
case *exec.ExitError:
|
||||
status := t.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
|
||||
os.Exit(status)
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "error: %s\n", err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isNomsExecutable(dir *os.File, name string) bool {
|
||||
if !strings.HasPrefix(name, cmdPrefix) || len(name) == len(cmdPrefix) {
|
||||
return false
|
||||
}
|
||||
|
||||
fi, err := os.Stat(path.Join(dir.Name(), name))
|
||||
return err == nil && !fi.IsDir() && fi.Mode()&0111 != 0
|
||||
|
||||
fmt.Fprintf(os.Stderr, "noms: unknown command %q\n", args[0])
|
||||
usage()
|
||||
}
|
||||
|
||||
67
cmd/noms/noms_command.go
Normal file
67
cmd/noms/noms_command.go
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright 2016 Attic Labs, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, version 2.0:
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type nomsCommand struct {
|
||||
// Run runs the command.
|
||||
// The args are the arguments after the command name.
|
||||
Run func(args []string) int
|
||||
|
||||
// UsageLine is the one-line usage message.
|
||||
// The first word in the line is taken to be the command name.
|
||||
UsageLine string
|
||||
|
||||
// Short is the short description shown in the 'noms help' output.
|
||||
Short string
|
||||
|
||||
// Long is the long message shown in the 'noms help <this-command>' output.
|
||||
Long string
|
||||
|
||||
// Flag is a set of flags specific to this command.
|
||||
Flags func() *flag.FlagSet
|
||||
|
||||
// Nargs is the minimum number of arguments expected after flags, specific to this command.
|
||||
Nargs int
|
||||
}
|
||||
|
||||
// Name returns the command's name: the first word in the usage line.
|
||||
func (nc *nomsCommand) Name() string {
|
||||
name := nc.UsageLine
|
||||
i := strings.Index(name, " ")
|
||||
if i >= 0 {
|
||||
name = name[:i]
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func countFlags(flags *flag.FlagSet) int {
|
||||
if flags == nil {
|
||||
return 0
|
||||
} else {
|
||||
n := 0
|
||||
flags.VisitAll(func(f *flag.Flag) {
|
||||
n++
|
||||
})
|
||||
return n
|
||||
}
|
||||
}
|
||||
|
||||
func (nc *nomsCommand) Usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: %s\n\n", nc.UsageLine)
|
||||
fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(nc.Long))
|
||||
flags := nc.Flags()
|
||||
if countFlags(flags) > 0 {
|
||||
fmt.Fprintf(os.Stderr, "\noptions:\n")
|
||||
flags.PrintDefaults()
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
66
cmd/noms/noms_diff.go
Normal file
66
cmd/noms/noms_diff.go
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright 2016 Attic Labs, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, version 2.0:
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/attic-labs/noms/cmd/noms/diff"
|
||||
"github.com/attic-labs/noms/go/d"
|
||||
"github.com/attic-labs/noms/go/spec"
|
||||
"github.com/attic-labs/noms/go/util/outputpager"
|
||||
)
|
||||
|
||||
const (
|
||||
addPrefix = "+ "
|
||||
subPrefix = "- "
|
||||
)
|
||||
|
||||
var nomsDiff = &nomsCommand{
|
||||
Run: runDiff,
|
||||
UsageLine: "diff <object1> <object2>",
|
||||
Short: "Shows the difference between two objects",
|
||||
Long: "See Spelling Objects at https://github.com/attic-labs/noms/blob/master/doc/spelling.md for details on the object arguments.",
|
||||
Flags: setupDiffFlags,
|
||||
Nargs: 2,
|
||||
}
|
||||
|
||||
func setupDiffFlags() *flag.FlagSet {
|
||||
diffFlagSet := flag.NewFlagSet("diff", flag.ExitOnError)
|
||||
outputpager.RegisterOutputpagerFlags(diffFlagSet)
|
||||
return diffFlagSet
|
||||
}
|
||||
|
||||
func runDiff(args []string) int {
|
||||
db1, value1, err := spec.GetPath(args[0])
|
||||
d.CheckErrorNoUsage(err)
|
||||
if value1 == nil {
|
||||
d.CheckErrorNoUsage(fmt.Errorf("Object not found: %s", args[0]))
|
||||
}
|
||||
defer db1.Close()
|
||||
|
||||
db2, value2, err := spec.GetPath(args[1])
|
||||
d.CheckErrorNoUsage(err)
|
||||
if value2 == nil {
|
||||
d.CheckErrorNoUsage(fmt.Errorf("Object not found: %s", args[1]))
|
||||
}
|
||||
defer db2.Close()
|
||||
|
||||
waitChan := outputpager.PageOutput(!outputpager.NoPager)
|
||||
|
||||
w := bufio.NewWriter(os.Stdout)
|
||||
diff.Diff(w, value1, value2)
|
||||
fmt.Fprintf(w, "\n")
|
||||
w.Flush()
|
||||
|
||||
if waitChan != nil {
|
||||
os.Stdout.Close()
|
||||
<-waitChan
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@@ -7,27 +7,31 @@ package main
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/attic-labs/noms/go/d"
|
||||
"github.com/attic-labs/noms/go/spec"
|
||||
"github.com/attic-labs/noms/go/types"
|
||||
)
|
||||
|
||||
func main() {
|
||||
toDelete := flag.String("d", "", "dataset to delete")
|
||||
var toDelete string
|
||||
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintln(os.Stderr, "Noms dataset management\n")
|
||||
fmt.Fprintln(os.Stderr, "Usage: noms ds [<database> | -d <dataset>]")
|
||||
flag.PrintDefaults()
|
||||
fmt.Fprintf(os.Stderr, "\nFor detailed information on spelling datastores and datasets, see: at https://github.com/attic-labs/noms/blob/master/doc/spelling.md.\n\n")
|
||||
}
|
||||
var nomsDs = &nomsCommand{
|
||||
Run: runDs,
|
||||
UsageLine: "ds [<database> | -d <dataset>]",
|
||||
Short: "Noms dataset management",
|
||||
Long: "See Spelling Objects at https://github.com/attic-labs/noms/blob/master/doc/spelling.md for details on the database and dataset arguments.",
|
||||
Flags: setupDsFlags,
|
||||
}
|
||||
|
||||
flag.Parse()
|
||||
func setupDsFlags() *flag.FlagSet {
|
||||
dsFlagSet := flag.NewFlagSet("ds", flag.ExitOnError)
|
||||
dsFlagSet.StringVar(&toDelete, "d", "", "dataset to delete")
|
||||
return dsFlagSet
|
||||
}
|
||||
|
||||
if *toDelete != "" {
|
||||
set, err := spec.GetDataset(*toDelete)
|
||||
func runDs(args []string) int {
|
||||
if toDelete != "" {
|
||||
set, err := spec.GetDataset(toDelete)
|
||||
d.CheckError(err)
|
||||
|
||||
oldCommitRef, errBool := set.MaybeHeadRef()
|
||||
@@ -41,12 +45,11 @@ func main() {
|
||||
|
||||
fmt.Printf("Deleted dataset %v (was %v)\n\n", set.ID(), oldCommitRef.TargetHash().String())
|
||||
} else {
|
||||
if flag.NArg() != 1 {
|
||||
flag.Usage()
|
||||
return
|
||||
if len(args) != 1 {
|
||||
d.CheckError(fmt.Errorf("Database arg missing"))
|
||||
}
|
||||
|
||||
store, err := spec.GetDatabase(flag.Arg(0))
|
||||
store, err := spec.GetDatabase(args[0])
|
||||
d.CheckError(err)
|
||||
defer store.Close()
|
||||
|
||||
@@ -54,5 +57,5 @@ func main() {
|
||||
fmt.Println(k)
|
||||
})
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/attic-labs/noms/go/chunks"
|
||||
"github.com/attic-labs/noms/go/d"
|
||||
"github.com/attic-labs/noms/go/datas"
|
||||
"github.com/attic-labs/noms/go/dataset"
|
||||
"github.com/attic-labs/noms/go/spec"
|
||||
@@ -17,14 +18,15 @@ import (
|
||||
)
|
||||
|
||||
func TestDs(t *testing.T) {
|
||||
suite.Run(t, &testSuite{})
|
||||
d.UtilExiter = testExiter{}
|
||||
suite.Run(t, &nomsDsTestSuite{})
|
||||
}
|
||||
|
||||
type testSuite struct {
|
||||
type nomsDsTestSuite struct {
|
||||
clienttest.ClientTestSuite
|
||||
}
|
||||
|
||||
func (s *testSuite) TestEmptyNomsDs() {
|
||||
func (s *nomsDsTestSuite) TestEmptyNomsDs() {
|
||||
dir := s.LdbDir
|
||||
|
||||
cs := chunks.NewLevelDBStore(dir+"/name", "", 24, false)
|
||||
@@ -33,11 +35,11 @@ func (s *testSuite) TestEmptyNomsDs() {
|
||||
ds.Close()
|
||||
|
||||
dbSpec := spec.CreateDatabaseSpecString("ldb", dir+"/name")
|
||||
rtnVal := s.Run(main, []string{dbSpec})
|
||||
rtnVal, _ := s.Run(main, []string{"ds", dbSpec})
|
||||
s.Equal("", rtnVal)
|
||||
}
|
||||
|
||||
func (s *testSuite) TestNomsDs() {
|
||||
func (s *nomsDsTestSuite) TestNomsDs() {
|
||||
dir := s.LdbDir
|
||||
|
||||
cs := chunks.NewLevelDBStore(dir+"/name", "", 24, false)
|
||||
@@ -61,26 +63,26 @@ func (s *testSuite) TestNomsDs() {
|
||||
dataset2Name := spec.CreateValueSpecString("ldb", dir+"/name", id2)
|
||||
|
||||
// both datasets show up
|
||||
rtnVal := s.Run(main, []string{dbSpec})
|
||||
rtnVal, _ := s.Run(main, []string{"ds", dbSpec})
|
||||
s.Equal(id+"\n"+id2+"\n", rtnVal)
|
||||
|
||||
// both datasets again, to make sure printing doesn't change them
|
||||
rtnVal = s.Run(main, []string{dbSpec})
|
||||
rtnVal, _ = s.Run(main, []string{"ds", dbSpec})
|
||||
s.Equal(id+"\n"+id2+"\n", rtnVal)
|
||||
|
||||
// delete one dataset, print message at delete
|
||||
rtnVal = s.Run(main, []string{"-d", datasetName})
|
||||
rtnVal, _ = s.Run(main, []string{"ds", "-d", datasetName})
|
||||
s.Equal("Deleted dataset "+id+" (was sha1-d54b79552cda9ebe8e446eeb19aab0e69b6ceee3)\n\n", rtnVal)
|
||||
|
||||
// print datasets, just one left
|
||||
rtnVal = s.Run(main, []string{dbSpec})
|
||||
rtnVal, _ = s.Run(main, []string{"ds", dbSpec})
|
||||
s.Equal(id2+"\n", rtnVal)
|
||||
|
||||
// delete the second dataset
|
||||
rtnVal = s.Run(main, []string{"-d", dataset2Name})
|
||||
rtnVal, _ = s.Run(main, []string{"ds", "-d", dataset2Name})
|
||||
s.Equal("Deleted dataset "+id2+" (was sha1-7b75b0ebfc2a0815ba6fb2b31d03c8f9976ae530)\n\n", rtnVal)
|
||||
|
||||
// print datasets, none left
|
||||
rtnVal = s.Run(main, []string{dbSpec})
|
||||
rtnVal, _ = s.Run(main, []string{"ds", dbSpec})
|
||||
s.Equal("", rtnVal)
|
||||
}
|
||||
85
cmd/noms/noms_help.go
Normal file
85
cmd/noms/noms_help.go
Normal file
@@ -0,0 +1,85 @@
|
||||
// Copyright 2016 Attic Labs, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, version 2.0:
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var usageTemplate = `Noms is a tool for iterating with Noms data.
|
||||
|
||||
Usage:
|
||||
|
||||
noms command [arguments]
|
||||
|
||||
The commands are:
|
||||
{{range .}}
|
||||
{{.Name | printf "%-11s"}} {{.Short}}{{end}}
|
||||
|
||||
Use "noms help [command]" for more information about a command.
|
||||
|
||||
`
|
||||
|
||||
var helpTemplate = `usage: noms {{.UsageLine}}
|
||||
|
||||
{{.Long | trim}}
|
||||
`
|
||||
|
||||
// tmpl executes the given template text on data, writing the result to w.
|
||||
func tmpl(w io.Writer, text string, data interface{}) {
|
||||
t := template.New("top")
|
||||
t.Funcs(template.FuncMap{"trim": strings.TrimSpace})
|
||||
template.Must(t.Parse(text))
|
||||
if err := t.Execute(w, data); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func printUsage(w io.Writer) {
|
||||
bw := bufio.NewWriter(w)
|
||||
tmpl(bw, usageTemplate, commands)
|
||||
bw.Flush()
|
||||
}
|
||||
|
||||
func usage() {
|
||||
printUsage(os.Stderr)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// help implements the 'help' command.
|
||||
func help(args []string) {
|
||||
if len(args) == 0 {
|
||||
printUsage(os.Stdout)
|
||||
// not exit 2: succeeded at 'noms help'.
|
||||
return
|
||||
}
|
||||
if len(args) != 1 {
|
||||
fmt.Fprintf(os.Stderr, "usage: noms help command\n\nToo many arguments given.\n")
|
||||
os.Exit(1) // failed at 'noms help'
|
||||
}
|
||||
|
||||
arg := args[0]
|
||||
|
||||
for _, cmd := range commands {
|
||||
if cmd.Name() == arg {
|
||||
tmpl(os.Stdout, helpTemplate, cmd)
|
||||
flags := cmd.Flags()
|
||||
if countFlags(flags) > 0 {
|
||||
fmt.Fprintf(os.Stdout, "\noptions:\n")
|
||||
flags.PrintDefaults()
|
||||
}
|
||||
// not exit 2: succeeded at 'noms help cmd'.
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "Unknown help topic %#q\n", arg)
|
||||
usage() // failed at 'noms help cmd'
|
||||
}
|
||||
@@ -7,7 +7,6 @@ package main
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -15,7 +14,7 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/attic-labs/noms/cmd/noms-diff/diff"
|
||||
"github.com/attic-labs/noms/cmd/noms/diff"
|
||||
"github.com/attic-labs/noms/go/d"
|
||||
"github.com/attic-labs/noms/go/datas"
|
||||
"github.com/attic-labs/noms/go/spec"
|
||||
@@ -26,62 +25,60 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
color, maxLines, maxCommits *int
|
||||
showHelp, showGraph, showValue *bool
|
||||
useColor = false
|
||||
useColor = false
|
||||
color int
|
||||
maxLines int
|
||||
maxCommits int
|
||||
showGraph bool
|
||||
showValue bool
|
||||
)
|
||||
|
||||
const parallelism = 16
|
||||
|
||||
func main() {
|
||||
color = flag.Int("color", -1, "value of 1 forces color on, 2 forces color off")
|
||||
maxLines = flag.Int("max-lines", 10, "max number of lines to show per commit (-1 for all lines)")
|
||||
maxCommits = flag.Int("n", 0, "max number of commits to display (0 for all commits)")
|
||||
showHelp = flag.Bool("help", false, "show help text")
|
||||
showGraph = flag.Bool("graph", false, "show ascii-based commit hierarcy on left side of output")
|
||||
showValue = flag.Bool("show-value", false, "show commit value rather than diff information -- this is temporary")
|
||||
var nomsLog = &nomsCommand{
|
||||
Run: runLog,
|
||||
UsageLine: "log [options] <commitObject>",
|
||||
Short: "Displays the history of a Noms dataset",
|
||||
Long: "commitObject must be a dataset or object spec that refers to a commit. See Spelling Objects at https://github.com/attic-labs/noms/blob/master/doc/spelling.md for details.",
|
||||
Flags: setupLogFlags,
|
||||
Nargs: 1,
|
||||
}
|
||||
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintln(os.Stderr, "Displays the history of a Noms dataset\n")
|
||||
fmt.Fprintln(os.Stderr, "Usage: noms log <commitObject>")
|
||||
fmt.Fprintln(os.Stderr, "commitObject must be a dataset or object spec that refers to a commit.")
|
||||
flag.PrintDefaults()
|
||||
fmt.Fprintf(os.Stderr, "\nSee \"Spelling Objects\" at https://github.com/attic-labs/noms/blob/master/doc/spelling.md for details on the object argument.\n\n")
|
||||
}
|
||||
|
||||
flag.Parse()
|
||||
if *showHelp {
|
||||
flag.Usage()
|
||||
return
|
||||
}
|
||||
|
||||
if len(flag.Args()) != 1 {
|
||||
d.CheckError(errors.New("expected exactly one argument"))
|
||||
}
|
||||
func setupLogFlags() *flag.FlagSet {
|
||||
logFlagSet := flag.NewFlagSet("log", flag.ExitOnError)
|
||||
logFlagSet.IntVar(&color, "color", -1, "value of 1 forces color on, 2 forces color off")
|
||||
logFlagSet.IntVar(&maxLines, "max-lines", 10, "max number of lines to show per commit (-1 for all lines)")
|
||||
logFlagSet.IntVar(&maxCommits, "n", 0, "max number of commits to display (0 for all commits)")
|
||||
logFlagSet.BoolVar(&showGraph, "graph", false, "show ascii-based commit hierarcy on left side of output")
|
||||
logFlagSet.BoolVar(&showValue, "show-value", false, "show commit value rather than diff information -- this is temporary")
|
||||
outputpager.RegisterOutputpagerFlags(logFlagSet)
|
||||
return logFlagSet
|
||||
}
|
||||
|
||||
func runLog(args []string) int {
|
||||
useColor = shouldUseColor()
|
||||
|
||||
database, value, err := spec.GetPath(flag.Arg(0))
|
||||
database, value, err := spec.GetPath(args[0])
|
||||
if err != nil {
|
||||
d.CheckErrorNoUsage(err)
|
||||
}
|
||||
defer database.Close()
|
||||
|
||||
if value == nil {
|
||||
d.CheckErrorNoUsage(fmt.Errorf("Object not found: %s", flag.Arg(0)))
|
||||
d.CheckErrorNoUsage(fmt.Errorf("Object not found: %s", args[0]))
|
||||
}
|
||||
|
||||
waitChan := outputpager.PageOutput(!*outputpager.NoPager)
|
||||
waitChan := outputpager.PageOutput(!outputpager.NoPager)
|
||||
|
||||
origCommit, ok := value.(types.Struct)
|
||||
if !ok || !origCommit.Type().Equals(datas.CommitType()) {
|
||||
d.CheckError(fmt.Errorf("%s does not reference a Commit object", flag.Arg(0)))
|
||||
d.CheckError(fmt.Errorf("%s does not reference a Commit object", args[0]))
|
||||
}
|
||||
|
||||
iter := NewCommitIterator(database, origCommit)
|
||||
displayed := 0
|
||||
if *maxCommits <= 0 {
|
||||
*maxCommits = math.MaxInt32
|
||||
if maxCommits <= 0 {
|
||||
maxCommits = math.MaxInt32
|
||||
}
|
||||
|
||||
inChan := make(chan interface{}, parallelism)
|
||||
@@ -92,7 +89,7 @@ func main() {
|
||||
}, parallelism)
|
||||
|
||||
go func() {
|
||||
for ln, ok := iter.Next(); ok && displayed < *maxCommits; ln, ok = iter.Next() {
|
||||
for ln, ok := iter.Next(); ok && displayed < maxCommits; ln, ok = iter.Next() {
|
||||
inChan <- ln
|
||||
displayed++
|
||||
}
|
||||
@@ -109,6 +106,7 @@ func main() {
|
||||
os.Stdout.Close()
|
||||
<-waitChan
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Prints the information for one commit in the log, including ascii graph on left side of commits if
|
||||
@@ -134,12 +132,12 @@ func printCommit(node LogNode, w io.Writer, db datas.Database) (err error) {
|
||||
} else {
|
||||
fmt.Fprintf(w, "%sParent: None\n", genGraph(node, lineno))
|
||||
}
|
||||
if *maxLines != 0 {
|
||||
if maxLines != 0 {
|
||||
var n int
|
||||
if *showValue {
|
||||
n, err = writeCommitLines(node, *maxLines, lineno, w)
|
||||
if showValue {
|
||||
n, err = writeCommitLines(node, maxLines, lineno, w)
|
||||
} else {
|
||||
n, err = writeDiffLines(node, db, *maxLines, lineno, w)
|
||||
n, err = writeDiffLines(node, db, maxLines, lineno, w)
|
||||
}
|
||||
lineno += n
|
||||
}
|
||||
@@ -148,7 +146,7 @@ func printCommit(node LogNode, w io.Writer, db datas.Database) (err error) {
|
||||
|
||||
// Generates ascii graph chars to display on the left side of the commit info if -graph arg is true.
|
||||
func genGraph(node LogNode, lineno int) string {
|
||||
if !*showGraph {
|
||||
if !showGraph {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -200,7 +198,7 @@ func genGraph(node LogNode, lineno int) string {
|
||||
}
|
||||
|
||||
func writeCommitLines(node LogNode, maxLines, lineno int, w io.Writer) (lineCnt int, err error) {
|
||||
mlw := &maxLineWriter{numLines: lineno, maxLines: maxLines, node: node, dest: w, needsPrefix: true}
|
||||
mlw := &maxLineWriter{numLines: lineno, maxLines: maxLines, node: node, dest: w, needsPrefix: true, showGraph: showGraph}
|
||||
err = types.WriteEncodedValueWithTags(mlw, node.commit.Get(datas.ValueField))
|
||||
d.PanicIfNotType(err, MaxLinesErr)
|
||||
if err != nil {
|
||||
@@ -216,7 +214,7 @@ func writeCommitLines(node LogNode, maxLines, lineno int, w io.Writer) (lineCnt
|
||||
}
|
||||
|
||||
func writeDiffLines(node LogNode, db datas.Database, maxLines, lineno int, w io.Writer) (lineCnt int, err error) {
|
||||
mlw := &maxLineWriter{numLines: lineno, maxLines: maxLines, node: node, dest: w, needsPrefix: true}
|
||||
mlw := &maxLineWriter{numLines: lineno, maxLines: maxLines, node: node, dest: w, needsPrefix: true, showGraph: showGraph}
|
||||
parents := node.commit.Get(datas.ParentsField).(types.Set)
|
||||
var parent types.Value = nil
|
||||
if parents.Len() > 0 {
|
||||
@@ -242,10 +240,10 @@ func writeDiffLines(node LogNode, db datas.Database, maxLines, lineno int, w io.
|
||||
}
|
||||
|
||||
func shouldUseColor() bool {
|
||||
if *color != 1 && *color != 0 {
|
||||
if color != 1 && color != 0 {
|
||||
return outputpager.IsStdoutTty()
|
||||
}
|
||||
return *color == 1
|
||||
return color == 1
|
||||
}
|
||||
|
||||
func max(i, j int) int {
|
||||
@@ -30,33 +30,34 @@ func (testExiter) Exit(code int) {
|
||||
panic(exitError{code})
|
||||
}
|
||||
|
||||
func TestNomsShow(t *testing.T) {
|
||||
func TestNomsLog(t *testing.T) {
|
||||
d.UtilExiter = testExiter{}
|
||||
suite.Run(t, &nomsShowTestSuite{})
|
||||
suite.Run(t, &nomsLogTestSuite{})
|
||||
}
|
||||
|
||||
type nomsShowTestSuite struct {
|
||||
type nomsLogTestSuite struct {
|
||||
clienttest.ClientTestSuite
|
||||
}
|
||||
|
||||
func testCommitInResults(s *nomsShowTestSuite, str string, i int) {
|
||||
func testCommitInResults(s *nomsLogTestSuite, str string, i int) {
|
||||
ds, err := spec.GetDataset(str)
|
||||
s.NoError(err)
|
||||
ds, err = ds.Commit(types.Number(i))
|
||||
s.NoError(err)
|
||||
commit := ds.Head()
|
||||
ds.Database().Close()
|
||||
s.Contains(s.Run(main, []string{str}), commit.Hash().String())
|
||||
res, _ := s.Run(main, []string{"log", str})
|
||||
s.Contains(res, commit.Hash().String())
|
||||
}
|
||||
|
||||
func (s *nomsShowTestSuite) TestNomsLog() {
|
||||
func (s *nomsLogTestSuite) TestNomsLog() {
|
||||
datasetName := "dsTest"
|
||||
str := spec.CreateValueSpecString("ldb", s.LdbDir, datasetName)
|
||||
ds, err := spec.GetDataset(str)
|
||||
s.NoError(err)
|
||||
|
||||
ds.Database().Close()
|
||||
s.Panics(func() { s.Run(main, []string{str}) })
|
||||
s.Panics(func() { s.Run(main, []string{"log", str}) })
|
||||
|
||||
testCommitInResults(s, str, 1)
|
||||
testCommitInResults(s, str, 2)
|
||||
@@ -78,7 +79,7 @@ func mergeDatasets(ds1, ds2 dataset.Dataset, v string) (dataset.Dataset, error)
|
||||
return ds1.CommitWithParents(types.String(v), types.NewSet(ds1.HeadRef(), ds2.HeadRef()))
|
||||
}
|
||||
|
||||
func (s *nomsShowTestSuite) TestNArg() {
|
||||
func (s *nomsLogTestSuite) TestNArg() {
|
||||
str := spec.CreateDatabaseSpecString("ldb", s.LdbDir)
|
||||
dsName := "nArgTest"
|
||||
db, err := spec.GetDatabase(str)
|
||||
@@ -98,21 +99,23 @@ func (s *nomsShowTestSuite) TestNArg() {
|
||||
db.Close()
|
||||
|
||||
dsSpec := spec.CreateValueSpecString("ldb", s.LdbDir, dsName)
|
||||
s.NotContains(s.Run(main, []string{"-n=1", dsSpec}), h1.String())
|
||||
res := s.Run(main, []string{"-n=0", dsSpec})
|
||||
res, _ := s.Run(main, []string{"log", "-n=1", dsSpec})
|
||||
s.NotContains(res, h1.String())
|
||||
res, _ = s.Run(main, []string{"log", "-n=0", dsSpec})
|
||||
s.Contains(res, h3.String())
|
||||
s.Contains(res, h2.String())
|
||||
s.Contains(res, h1.String())
|
||||
|
||||
vSpec := spec.CreateValueSpecString("ldb", s.LdbDir, "#"+h3.String())
|
||||
s.NotContains(s.Run(main, []string{"-n=1", vSpec}), h1.String())
|
||||
res = s.Run(main, []string{"-n=0", vSpec})
|
||||
res, _ = s.Run(main, []string{"log", "-n=1", vSpec})
|
||||
s.NotContains(res, h1.String())
|
||||
res, _ = s.Run(main, []string{"log", "-n=0", vSpec})
|
||||
s.Contains(res, h3.String())
|
||||
s.Contains(res, h2.String())
|
||||
s.Contains(res, h1.String())
|
||||
}
|
||||
|
||||
func (s *nomsShowTestSuite) TestNomsGraph1() {
|
||||
func (s *nomsLogTestSuite) TestNomsGraph1() {
|
||||
str := spec.CreateDatabaseSpecString("ldb", s.LdbDir)
|
||||
db, err := spec.GetDatabase(str)
|
||||
s.NoError(err)
|
||||
@@ -159,11 +162,13 @@ func (s *nomsShowTestSuite) TestNomsGraph1() {
|
||||
s.NoError(err)
|
||||
|
||||
b1.Database().Close()
|
||||
s.Equal(graphRes1, s.Run(main, []string{"-graph", "-show-value=true", spec.CreateValueSpecString("ldb", s.LdbDir, "b1")}))
|
||||
s.Equal(diffRes1, s.Run(main, []string{"-graph", "-show-value=false", spec.CreateValueSpecString("ldb", s.LdbDir, "b1")}))
|
||||
res, _ := s.Run(main, []string{"log", "-graph", "-show-value=true", spec.CreateValueSpecString("ldb", s.LdbDir, "b1")})
|
||||
s.Equal(graphRes1, res)
|
||||
res, _ = s.Run(main, []string{"log", "-graph", "-show-value=false", spec.CreateValueSpecString("ldb", s.LdbDir, "b1")})
|
||||
s.Equal(diffRes1, res)
|
||||
}
|
||||
|
||||
func (s *nomsShowTestSuite) TestNomsGraph2() {
|
||||
func (s *nomsLogTestSuite) TestNomsGraph2() {
|
||||
str := spec.CreateDatabaseSpecString("ldb", s.LdbDir)
|
||||
db, err := spec.GetDatabase(str)
|
||||
s.NoError(err)
|
||||
@@ -188,11 +193,14 @@ func (s *nomsShowTestSuite) TestNomsGraph2() {
|
||||
s.NoError(err)
|
||||
|
||||
db.Close()
|
||||
s.Equal(graphRes2, s.Run(main, []string{"-graph", "-show-value=true", spec.CreateValueSpecString("ldb", s.LdbDir, "ba")}))
|
||||
s.Equal(diffRes2, s.Run(main, []string{"-graph", "-show-value=false", spec.CreateValueSpecString("ldb", s.LdbDir, "ba")}))
|
||||
|
||||
res, _ := s.Run(main, []string{"log", "-graph", "-show-value=true", spec.CreateValueSpecString("ldb", s.LdbDir, "ba")})
|
||||
s.Equal(graphRes2, res)
|
||||
res, _ = s.Run(main, []string{"log", "-graph", "-show-value=false", spec.CreateValueSpecString("ldb", s.LdbDir, "ba")})
|
||||
s.Equal(diffRes2, res)
|
||||
}
|
||||
|
||||
func (s *nomsShowTestSuite) TestNomsGraph3() {
|
||||
func (s *nomsLogTestSuite) TestNomsGraph3() {
|
||||
str := spec.CreateDatabaseSpecString("ldb", s.LdbDir)
|
||||
db, err := spec.GetDatabase(str)
|
||||
s.NoError(err)
|
||||
@@ -227,11 +235,13 @@ func (s *nomsShowTestSuite) TestNomsGraph3() {
|
||||
s.NoError(err)
|
||||
|
||||
db.Close()
|
||||
s.Equal(graphRes3, s.Run(main, []string{"-graph", "-show-value=true", spec.CreateValueSpecString("ldb", s.LdbDir, "w")}))
|
||||
s.Equal(diffRes3, s.Run(main, []string{"-graph", "-show-value=false", spec.CreateValueSpecString("ldb", s.LdbDir, "w")}))
|
||||
res, _ := s.Run(main, []string{"log", "-graph", "-show-value=true", spec.CreateValueSpecString("ldb", s.LdbDir, "w")})
|
||||
s.Equal(graphRes3, res)
|
||||
res, _ = s.Run(main, []string{"log", "-graph", "-show-value=false", spec.CreateValueSpecString("ldb", s.LdbDir, "w")})
|
||||
s.Equal(diffRes3, res)
|
||||
}
|
||||
|
||||
func (s *nomsShowTestSuite) TestTruncation() {
|
||||
func (s *nomsLogTestSuite) TestTruncation() {
|
||||
toNomsList := func(l []string) types.List {
|
||||
nv := []types.Value{}
|
||||
for _, v := range l {
|
||||
@@ -255,14 +265,20 @@ func (s *nomsShowTestSuite) TestTruncation() {
|
||||
db.Close()
|
||||
|
||||
dsSpec := spec.CreateValueSpecString("ldb", s.LdbDir, "truncate")
|
||||
s.Equal(truncRes1, s.Run(main, []string{"-graph", "-show-value=true", dsSpec}))
|
||||
s.Equal(diffTrunc1, s.Run(main, []string{"-graph", "-show-value=false", dsSpec}))
|
||||
res, _ := s.Run(main, []string{"log", "-graph", "-show-value=true", dsSpec})
|
||||
s.Equal(truncRes1, res)
|
||||
res, _ = s.Run(main, []string{"log", "-graph", "-show-value=false", dsSpec})
|
||||
s.Equal(diffTrunc1, res)
|
||||
|
||||
s.Equal(truncRes2, s.Run(main, []string{"-graph", "-show-value=true", "-max-lines=-1", dsSpec}))
|
||||
s.Equal(diffTrunc2, s.Run(main, []string{"-graph", "-show-value=false", "-max-lines=-1", dsSpec}))
|
||||
res, _ = s.Run(main, []string{"log", "-graph", "-show-value=true", "-max-lines=-1", dsSpec})
|
||||
s.Equal(truncRes2, res)
|
||||
res, _ = s.Run(main, []string{"log", "-graph", "-show-value=false", "-max-lines=-1", dsSpec})
|
||||
s.Equal(diffTrunc2, res)
|
||||
|
||||
s.Equal(truncRes3, s.Run(main, []string{"-graph", "-show-value=true", "-max-lines=0", dsSpec}))
|
||||
s.Equal(diffTrunc3, s.Run(main, []string{"-graph", "-show-value=false", "-max-lines=0", dsSpec}))
|
||||
res, _ = s.Run(main, []string{"log", "-graph", "-show-value=true", "-max-lines=0", dsSpec})
|
||||
s.Equal(truncRes3, res)
|
||||
res, _ = s.Run(main, []string{"log", "-graph", "-show-value=false", "-max-lines=0", dsSpec})
|
||||
s.Equal(diffTrunc3, res)
|
||||
}
|
||||
|
||||
func TestBranchlistSplice(t *testing.T) {
|
||||
58
cmd/noms/noms_serve.go
Normal file
58
cmd/noms/noms_serve.go
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright 2016 Attic Labs, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, version 2.0:
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/attic-labs/noms/go/d"
|
||||
"github.com/attic-labs/noms/go/datas"
|
||||
"github.com/attic-labs/noms/go/spec"
|
||||
"github.com/attic-labs/noms/go/util/profile"
|
||||
)
|
||||
|
||||
var (
|
||||
port int
|
||||
)
|
||||
|
||||
var nomsServe = &nomsCommand{
|
||||
Run: runServe,
|
||||
UsageLine: "serve [options] <database>",
|
||||
Short: "Serves a Noms database over HTTP",
|
||||
Long: "See Spelling Objects at https://github.com/attic-labs/noms/blob/master/doc/spelling.md for details on the database argument.",
|
||||
Flags: setupServeFlags,
|
||||
Nargs: 1,
|
||||
}
|
||||
|
||||
func setupServeFlags() *flag.FlagSet {
|
||||
serveFlagSet := flag.NewFlagSet("serve", flag.ExitOnError)
|
||||
serveFlagSet.IntVar(&port, "port", 8000, "port to listen on for HTTP requests")
|
||||
spec.RegisterDatabaseFlags(serveFlagSet)
|
||||
return serveFlagSet
|
||||
}
|
||||
|
||||
func runServe(args []string) int {
|
||||
cs, err := spec.GetChunkStore(args[0])
|
||||
d.CheckError(err)
|
||||
server := datas.NewRemoteDatabaseServer(cs, port)
|
||||
|
||||
// Shutdown server gracefully so that profile may be written
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt)
|
||||
signal.Notify(c, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-c
|
||||
server.Stop()
|
||||
}()
|
||||
|
||||
d.Try(func() {
|
||||
defer profile.MaybeStartProfile().Stop()
|
||||
server.Run()
|
||||
})
|
||||
return 0
|
||||
}
|
||||
56
cmd/noms/noms_show.go
Normal file
56
cmd/noms/noms_show.go
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright 2016 Attic Labs, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, version 2.0:
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/attic-labs/noms/go/d"
|
||||
"github.com/attic-labs/noms/go/spec"
|
||||
"github.com/attic-labs/noms/go/types"
|
||||
"github.com/attic-labs/noms/go/util/outputpager"
|
||||
)
|
||||
|
||||
var nomsShow = &nomsCommand{
|
||||
Run: runShow,
|
||||
UsageLine: "show <object>",
|
||||
Short: "Shows a serialization of a Noms object",
|
||||
Long: "See Spelling Objects at https://github.com/attic-labs/noms/blob/master/doc/spelling.md for details on the object argument.",
|
||||
Flags: setupShowFlags,
|
||||
Nargs: 1,
|
||||
}
|
||||
|
||||
func setupShowFlags() *flag.FlagSet {
|
||||
showFlagSet := flag.NewFlagSet("show", flag.ExitOnError)
|
||||
outputpager.RegisterOutputpagerFlags(showFlagSet)
|
||||
return showFlagSet
|
||||
}
|
||||
|
||||
func runShow(args []string) int {
|
||||
database, value, err := spec.GetPath(args[0])
|
||||
d.CheckErrorNoUsage(err)
|
||||
|
||||
if value == nil {
|
||||
fmt.Fprintf(os.Stderr, "Object not found: %s\n", args[0])
|
||||
return 0
|
||||
}
|
||||
|
||||
waitChan := outputpager.PageOutput(!outputpager.NoPager)
|
||||
|
||||
w := bufio.NewWriter(os.Stdout)
|
||||
types.WriteEncodedValueWithTags(w, value)
|
||||
fmt.Fprintf(w, "\n")
|
||||
w.Flush()
|
||||
database.Close()
|
||||
|
||||
if waitChan != nil {
|
||||
os.Stdout.Close()
|
||||
<-waitChan
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@@ -49,18 +49,23 @@ func (s *nomsShowTestSuite) TestNomsShow() {
|
||||
|
||||
s1 := types.String("test string")
|
||||
r := writeTestData(str, s1)
|
||||
s.Equal(res1, s.Run(main, []string{str}))
|
||||
res, _ := s.Run(main, []string{"show", str})
|
||||
s.Equal(res1, res)
|
||||
|
||||
str1 := spec.CreateValueSpecString("ldb", s.LdbDir, "#"+r.TargetHash().String())
|
||||
s.Equal(res2, s.Run(main, []string{str1}))
|
||||
res, _ = s.Run(main, []string{"show", str1})
|
||||
s.Equal(res2, res)
|
||||
|
||||
list := types.NewList(types.String("elem1"), types.Number(2), types.String("elem3"))
|
||||
r = writeTestData(str, list)
|
||||
s.Equal(res3, s.Run(main, []string{str}))
|
||||
res, _ = s.Run(main, []string{"show", str})
|
||||
s.Equal(res3, res)
|
||||
|
||||
str1 = spec.CreateValueSpecString("ldb", s.LdbDir, "#"+r.TargetHash().String())
|
||||
s.Equal(res4, s.Run(main, []string{str1}))
|
||||
res, _ = s.Run(main, []string{"show", str1})
|
||||
s.Equal(res4, res)
|
||||
|
||||
_ = writeTestData(str, s1)
|
||||
s.Equal(res5, s.Run(main, []string{str}))
|
||||
res, _ = s.Run(main, []string{"show", str})
|
||||
s.Equal(res5, res)
|
||||
}
|
||||
60
cmd/noms/noms_sync.go
Normal file
60
cmd/noms/noms_sync.go
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright 2016 Attic Labs, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, version 2.0:
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
|
||||
"github.com/attic-labs/noms/go/d"
|
||||
"github.com/attic-labs/noms/go/spec"
|
||||
"github.com/attic-labs/noms/go/types"
|
||||
"github.com/attic-labs/noms/go/util/profile"
|
||||
)
|
||||
|
||||
var (
|
||||
p int
|
||||
)
|
||||
|
||||
var nomsSync = &nomsCommand{
|
||||
Run: runSync,
|
||||
UsageLine: "sync [options] <source-object> <dest-dataset>",
|
||||
Short: "Moves datasets between or within databases",
|
||||
Long: "See Spelling Objects at https://github.com/attic-labs/noms/blob/master/doc/spelling.md for details on the object and dataset arguments.",
|
||||
Flags: setupSyncFlags,
|
||||
Nargs: 2,
|
||||
}
|
||||
|
||||
func setupSyncFlags() *flag.FlagSet {
|
||||
syncFlagSet := flag.NewFlagSet("sync", flag.ExitOnError)
|
||||
syncFlagSet.IntVar(&p, "p", 512, "parallelism")
|
||||
spec.RegisterDatabaseFlags(syncFlagSet)
|
||||
profile.RegisterProfileFlags(syncFlagSet)
|
||||
return syncFlagSet
|
||||
}
|
||||
|
||||
func runSync(args []string) int {
|
||||
|
||||
sourceStore, sourceObj, err := spec.GetPath(args[0])
|
||||
d.CheckError(err)
|
||||
defer sourceStore.Close()
|
||||
|
||||
sinkDataset, err := spec.GetDataset(args[1])
|
||||
d.CheckError(err)
|
||||
defer sinkDataset.Database().Close()
|
||||
|
||||
err = d.Try(func() {
|
||||
defer profile.MaybeStartProfile().Stop()
|
||||
|
||||
var err error
|
||||
sinkDataset, err = sinkDataset.Pull(sourceStore, types.NewRef(sourceObj), p)
|
||||
d.PanicIfError(err)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@@ -18,14 +18,14 @@ import (
|
||||
)
|
||||
|
||||
func TestSync(t *testing.T) {
|
||||
suite.Run(t, &testSuite{})
|
||||
suite.Run(t, &nomsSyncTestSuite{})
|
||||
}
|
||||
|
||||
type testSuite struct {
|
||||
type nomsSyncTestSuite struct {
|
||||
clienttest.ClientTestSuite
|
||||
}
|
||||
|
||||
func (s *testSuite) TestSync() {
|
||||
func (s *nomsSyncTestSuite) TestSync() {
|
||||
source1 := dataset.NewDataset(datas.NewDatabase(chunks.NewLevelDBStore(s.LdbDir, "", 1, false)), "foo")
|
||||
source1, err := source1.Commit(types.Number(42))
|
||||
s.NoError(err)
|
||||
@@ -37,7 +37,7 @@ func (s *testSuite) TestSync() {
|
||||
sourceSpec := spec.CreateValueSpecString("ldb", s.LdbDir, "#"+source1HeadRef.String())
|
||||
ldb2dir := path.Join(s.TempDir, "ldb2")
|
||||
sinkDatasetSpec := spec.CreateValueSpecString("ldb", ldb2dir, "bar")
|
||||
out := s.Run(main, []string{sourceSpec, sinkDatasetSpec})
|
||||
out, _ := s.Run(main, []string{"sync", sourceSpec, sinkDatasetSpec})
|
||||
s.Equal("", out)
|
||||
|
||||
dest := dataset.NewDataset(datas.NewDatabase(chunks.NewLevelDBStore(ldb2dir, "", 1, false)), "bar")
|
||||
@@ -45,7 +45,7 @@ func (s *testSuite) TestSync() {
|
||||
dest.Database().Close()
|
||||
|
||||
sourceDataset := spec.CreateValueSpecString("ldb", s.LdbDir, "foo")
|
||||
out = s.Run(main, []string{sourceDataset, sinkDatasetSpec})
|
||||
out, _ = s.Run(main, []string{"sync", sourceDataset, sinkDatasetSpec})
|
||||
s.Equal("", out)
|
||||
|
||||
dest = dataset.NewDataset(datas.NewDatabase(chunks.NewLevelDBStore(ldb2dir, "", 1, false)), "bar")
|
||||
32
cmd/noms/noms_version.go
Normal file
32
cmd/noms/noms_version.go
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright 2016 Attic Labs, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, version 2.0:
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/attic-labs/noms/go/constants"
|
||||
)
|
||||
|
||||
var nomsVersion = &nomsCommand{
|
||||
Run: runVersion,
|
||||
UsageLine: "version ",
|
||||
Short: "Display noms version",
|
||||
Long: "version prints the Noms data version and build identifier",
|
||||
Flags: setupVersionFlags,
|
||||
Nargs: 0,
|
||||
}
|
||||
|
||||
func setupVersionFlags() *flag.FlagSet {
|
||||
return flag.NewFlagSet("version", flag.ExitOnError)
|
||||
}
|
||||
|
||||
func runVersion(args []string) int {
|
||||
fmt.Fprintf(os.Stdout, "version: %v\n", constants.NomsVersion)
|
||||
fmt.Fprintf(os.Stdout, "built from %v\n", constants.NomsGitSHA)
|
||||
return 0
|
||||
}
|
||||
28
cmd/noms/noms_version_test.go
Normal file
28
cmd/noms/noms_version_test.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright 2016 Attic Labs, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, version 2.0:
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/attic-labs/noms/go/constants"
|
||||
"github.com/attic-labs/noms/go/util/clienttest"
|
||||
"github.com/attic-labs/testify/suite"
|
||||
)
|
||||
|
||||
func TestVersion(t *testing.T) {
|
||||
suite.Run(t, &nomsVersionTestSuite{})
|
||||
}
|
||||
|
||||
type nomsVersionTestSuite struct {
|
||||
clienttest.ClientTestSuite
|
||||
}
|
||||
|
||||
func (s *nomsVersionTestSuite) TestVersion() {
|
||||
val, _ := s.Run(main, []string{"version"})
|
||||
expectedVal := fmt.Sprintf("version: %v\nbuilt from %v\n", constants.NomsVersion, constants.NomsGitSHA)
|
||||
s.Equal(val, expectedVal)
|
||||
}
|
||||
@@ -36,11 +36,11 @@ var (
|
||||
flagsRegistered = false
|
||||
)
|
||||
|
||||
func RegisterLevelDBFlags() {
|
||||
func RegisterLevelDBFlags(flags *flag.FlagSet) {
|
||||
if !flagsRegistered {
|
||||
flagsRegistered = true
|
||||
flag.IntVar(&ldbFlags.maxFileHandles, "ldb-max-file-handles", 24, "max number of open file handles")
|
||||
flag.BoolVar(&ldbFlags.dumpStats, "ldb-dump-stats", false, "print get/has/put counts on close")
|
||||
flags.IntVar(&ldbFlags.maxFileHandles, "ldb-max-file-handles", 24, "max number of open file handles")
|
||||
flags.BoolVar(&ldbFlags.dumpStats, "ldb-dump-stats", false, "print get/has/put counts on close")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,3 +6,5 @@ package constants
|
||||
|
||||
// TODO: generate this from some central thing with go generate, so that JS and Go can be easily kept in sync
|
||||
const NomsVersion = "2"
|
||||
|
||||
var NomsGitSHA = "Developer Mode"
|
||||
|
||||
@@ -32,6 +32,7 @@ const boolSize = uint64(1)
|
||||
const structSize = uint64(64)
|
||||
|
||||
func main() {
|
||||
profile.RegisterProfileFlags(flag.CommandLine)
|
||||
flag.Parse()
|
||||
|
||||
buildCount := *count
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package spec
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"regexp"
|
||||
@@ -220,8 +221,8 @@ func (spec pathSpec) Value() (db datas.Database, val types.Value, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func RegisterDatabaseFlags() {
|
||||
chunks.RegisterLevelDBFlags()
|
||||
func RegisterDatabaseFlags(flags *flag.FlagSet) {
|
||||
chunks.RegisterLevelDBFlags(flags)
|
||||
}
|
||||
|
||||
// Utility functions to create specs
|
||||
|
||||
@@ -19,31 +19,37 @@ type ClientTestSuite struct {
|
||||
TempDir string
|
||||
LdbDir string
|
||||
out *os.File
|
||||
err *os.File
|
||||
}
|
||||
|
||||
func (suite *ClientTestSuite) SetupSuite() {
|
||||
dir, err := ioutil.TempDir(os.TempDir(), "nomstest")
|
||||
d.Chk.NoError(err)
|
||||
out, err := ioutil.TempFile(dir, "out")
|
||||
stdOutput, err := ioutil.TempFile(dir, "out")
|
||||
d.Chk.NoError(err)
|
||||
errOutput, err := ioutil.TempFile(dir, "err")
|
||||
d.Chk.NoError(err)
|
||||
|
||||
suite.TempDir = dir
|
||||
suite.LdbDir = path.Join(dir, "ldb")
|
||||
suite.out = out
|
||||
suite.out = stdOutput
|
||||
suite.err = errOutput
|
||||
}
|
||||
|
||||
func (suite *ClientTestSuite) TearDownSuite() {
|
||||
suite.out.Close()
|
||||
suite.err.Close()
|
||||
defer d.Chk.NoError(os.RemoveAll(suite.TempDir))
|
||||
}
|
||||
|
||||
func (suite *ClientTestSuite) Run(m func(), args []string) string {
|
||||
func (suite *ClientTestSuite) Run(m func(), args []string) (stdout string, stderr string) {
|
||||
origArgs := os.Args
|
||||
origOut := os.Stdout
|
||||
origErr := os.Stderr
|
||||
|
||||
os.Args = append([]string{"cmd"}, args...)
|
||||
os.Stdout = suite.out
|
||||
os.Stderr = suite.err
|
||||
|
||||
defer func() {
|
||||
os.Args = origArgs
|
||||
@@ -56,7 +62,7 @@ func (suite *ClientTestSuite) Run(m func(), args []string) string {
|
||||
|
||||
_, err := suite.out.Seek(0, 0)
|
||||
d.Chk.NoError(err)
|
||||
b, err := ioutil.ReadAll(os.Stdout)
|
||||
capturedOut, err := ioutil.ReadAll(os.Stdout)
|
||||
d.Chk.NoError(err)
|
||||
|
||||
_, err = suite.out.Seek(0, 0)
|
||||
@@ -64,5 +70,15 @@ func (suite *ClientTestSuite) Run(m func(), args []string) string {
|
||||
err = suite.out.Truncate(0)
|
||||
d.Chk.NoError(err)
|
||||
|
||||
return string(b)
|
||||
_, err = suite.err.Seek(0, 0)
|
||||
d.Chk.NoError(err)
|
||||
capturedErr, err := ioutil.ReadAll(os.Stderr)
|
||||
d.Chk.NoError(err)
|
||||
|
||||
_, err = suite.err.Seek(0, 0)
|
||||
d.Chk.NoError(err)
|
||||
err = suite.err.Truncate(0)
|
||||
d.Chk.NoError(err)
|
||||
|
||||
return string(capturedOut), string(capturedErr)
|
||||
}
|
||||
|
||||
@@ -14,9 +14,17 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
NoPager = flag.Bool("no-pager", false, "suppress paging functionality")
|
||||
NoPager bool
|
||||
flagsRegistered = false
|
||||
)
|
||||
|
||||
func RegisterOutputpagerFlags(flags *flag.FlagSet) {
|
||||
if !flagsRegistered {
|
||||
flagsRegistered = true
|
||||
flags.BoolVar(&NoPager, "no-pager", false, "suppress paging functionality")
|
||||
}
|
||||
}
|
||||
|
||||
func PageOutput(usePager bool) <-chan struct{} {
|
||||
if !usePager || !IsStdoutTty() {
|
||||
return nil
|
||||
|
||||
@@ -15,30 +15,40 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
cpuProfile = flag.String("cpuprofile", "", "write cpu profile to file")
|
||||
memProfile = flag.String("memprofile", "", "write memory profile to this file")
|
||||
blockProfile = flag.String("blockprofile", "", "write block profile to this file")
|
||||
cpuProfile string
|
||||
memProfile string
|
||||
blockProfile string
|
||||
flagsRegistered = false
|
||||
)
|
||||
|
||||
func RegisterProfileFlags(flags *flag.FlagSet) {
|
||||
if !flagsRegistered {
|
||||
flagsRegistered = true
|
||||
flags.StringVar(&cpuProfile, "cpuprofile", "", "write cpu profile to file")
|
||||
flags.StringVar(&memProfile, "memprofile", "", "write memory profile to this file")
|
||||
flags.StringVar(&blockProfile, "blockprofile", "", "write block profile to this file")
|
||||
}
|
||||
}
|
||||
|
||||
// MaybeStartProfile checks the -blockProfile, -cpuProfile, and -memProfile flag and, for each that is set, attempts to start gathering profiling data into the appropriate files. It returns an object with one method, Stop(), that must be called in order to flush profile data to disk before the process terminates.
|
||||
func MaybeStartProfile() interface {
|
||||
Stop()
|
||||
} {
|
||||
p := &prof{}
|
||||
if *blockProfile != "" {
|
||||
f, err := os.Create(*blockProfile)
|
||||
if blockProfile != "" {
|
||||
f, err := os.Create(blockProfile)
|
||||
d.PanicIfError(err)
|
||||
runtime.SetBlockProfileRate(1)
|
||||
p.bp = f
|
||||
}
|
||||
if *cpuProfile != "" {
|
||||
f, err := os.Create(*cpuProfile)
|
||||
if cpuProfile != "" {
|
||||
f, err := os.Create(cpuProfile)
|
||||
d.PanicIfError(err)
|
||||
pprof.StartCPUProfile(f)
|
||||
p.cpu = f
|
||||
}
|
||||
if *memProfile != "" {
|
||||
f, err := os.Create(*memProfile)
|
||||
if memProfile != "" {
|
||||
f, err := os.Create(memProfile)
|
||||
d.PanicIfError(err)
|
||||
p.mem = f
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@ func main() {
|
||||
fmt.Fprintf(os.Stderr, "usage: %s [options] <dataset>\n", os.Args[0])
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
|
||||
spec.RegisterDatabaseFlags(flag.CommandLine)
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if flag.NArg() != 1 {
|
||||
|
||||
@@ -23,7 +23,13 @@ type counterTestSuite struct {
|
||||
func (s *counterTestSuite) TestCounter() {
|
||||
spec := spec.CreateValueSpecString("ldb", s.LdbDir, "counter")
|
||||
args := []string{spec}
|
||||
s.Equal("1\n", s.Run(main, args))
|
||||
s.Equal("2\n", s.Run(main, args))
|
||||
s.Equal("3\n", s.Run(main, args))
|
||||
stdout, stderr := s.Run(main, args)
|
||||
s.Equal("1\n", stdout)
|
||||
s.Equal("", stderr)
|
||||
stdout, stderr = s.Run(main, args)
|
||||
s.Equal("2\n", stdout)
|
||||
s.Equal("", stderr)
|
||||
stdout, stderr = s.Run(main, args)
|
||||
s.Equal("3\n", stdout)
|
||||
s.Equal("", stderr)
|
||||
}
|
||||
|
||||
@@ -23,7 +23,8 @@ var (
|
||||
)
|
||||
|
||||
func main() {
|
||||
spec.RegisterDatabaseFlags()
|
||||
spec.RegisterDatabaseFlags(flag.CommandLine)
|
||||
profile.RegisterProfileFlags(flag.CommandLine)
|
||||
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintln(os.Stderr, "Usage: csv-export [options] dataset > filename")
|
||||
|
||||
@@ -67,10 +67,11 @@ func (s *testSuite) TestCSVExporter() {
|
||||
|
||||
// Run exporter
|
||||
dataspec := spec.CreateValueSpecString("ldb", s.LdbDir, setName)
|
||||
out := s.Run(main, []string{dataspec})
|
||||
stdout, stderr := s.Run(main, []string{dataspec})
|
||||
s.Equal("", stderr)
|
||||
|
||||
// Verify output
|
||||
csvReader := csv.NewReader(strings.NewReader(out))
|
||||
csvReader := csv.NewReader(strings.NewReader(stdout))
|
||||
|
||||
row, err := csvReader.Read()
|
||||
d.Chk.NoError(err)
|
||||
|
||||
@@ -43,7 +43,8 @@ func main() {
|
||||
destTypePattern = regexp.MustCompile("^(list|map):(\\d+)$")
|
||||
)
|
||||
|
||||
spec.RegisterDatabaseFlags()
|
||||
spec.RegisterDatabaseFlags(flag.CommandLine)
|
||||
profile.RegisterProfileFlags(flag.CommandLine)
|
||||
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintf(os.Stderr, "Usage: csv-import [options] <dataset> <csvfile>\n\n")
|
||||
|
||||
@@ -45,8 +45,9 @@ func (s *testSuite) TestCSVImporter() {
|
||||
|
||||
setName := "csv"
|
||||
dataspec := spec.CreateValueSpecString("ldb", s.LdbDir, setName)
|
||||
out := s.Run(main, []string{"-no-progress", "-column-types", "String,Number", dataspec, input.Name()})
|
||||
s.Equal("", out)
|
||||
stdout, stderr := s.Run(main, []string{"-no-progress", "-column-types", "String,Number", dataspec, input.Name()})
|
||||
s.Equal("", stdout)
|
||||
s.Equal("", stderr)
|
||||
|
||||
cs := chunks.NewLevelDBStore(s.LdbDir, "", 1, false)
|
||||
ds := dataset.NewDataset(datas.NewDatabase(cs), setName)
|
||||
@@ -83,8 +84,9 @@ func (s *testSuite) TestCSVImporterToMap() {
|
||||
|
||||
setName := "csv"
|
||||
dataspec := spec.CreateValueSpecString("ldb", s.LdbDir, setName)
|
||||
out := s.Run(main, []string{"-no-progress", "-column-types", "String,Number,Number", "-dest-type", "map:1", dataspec, input.Name()})
|
||||
s.Equal("", out)
|
||||
stdout, stderr := s.Run(main, []string{"-no-progress", "-column-types", "String,Number,Number", "-dest-type", "map:1", dataspec, input.Name()})
|
||||
s.Equal("", stdout)
|
||||
s.Equal("", stderr)
|
||||
|
||||
cs := chunks.NewLevelDBStore(s.LdbDir, "", 1, false)
|
||||
ds := dataset.NewDataset(datas.NewDatabase(cs), setName)
|
||||
@@ -113,8 +115,9 @@ func (s *testSuite) TestCSVImporterWithPipe() {
|
||||
|
||||
setName := "csv"
|
||||
dataspec := spec.CreateValueSpecString("ldb", s.LdbDir, setName)
|
||||
out := s.Run(main, []string{"-no-progress", "-column-types", "String,Number", "-delimiter", "|", dataspec, input.Name()})
|
||||
s.Equal("", out)
|
||||
stdout, stderr := s.Run(main, []string{"-no-progress", "-column-types", "String,Number", "-delimiter", "|", dataspec, input.Name()})
|
||||
s.Equal("", stdout)
|
||||
s.Equal("", stderr)
|
||||
|
||||
cs := chunks.NewLevelDBStore(s.LdbDir, "", 1, false)
|
||||
ds := dataset.NewDataset(datas.NewDatabase(cs), setName)
|
||||
@@ -140,8 +143,9 @@ func (s *testSuite) TestCSVImporterWithExternalHeader() {
|
||||
|
||||
setName := "csv"
|
||||
dataspec := spec.CreateValueSpecString("ldb", s.LdbDir, setName)
|
||||
out := s.Run(main, []string{"-no-progress", "-column-types", "String,Number", "-header", "x,y", dataspec, input.Name()})
|
||||
s.Equal("", out)
|
||||
stdout, stderr := s.Run(main, []string{"-no-progress", "-column-types", "String,Number", "-header", "x,y", dataspec, input.Name()})
|
||||
s.Equal("", stdout)
|
||||
s.Equal("", stderr)
|
||||
|
||||
cs := chunks.NewLevelDBStore(s.LdbDir, "", 1, false)
|
||||
ds := dataset.NewDataset(datas.NewDatabase(cs), setName)
|
||||
|
||||
@@ -23,7 +23,7 @@ func usage() {
|
||||
}
|
||||
|
||||
func main() {
|
||||
chunks.RegisterLevelDBFlags()
|
||||
chunks.RegisterLevelDBFlags(flag.CommandLine)
|
||||
dynFlags := chunks.DynamoFlags("")
|
||||
|
||||
flag.Usage = usage
|
||||
|
||||
@@ -26,19 +26,24 @@ type testSuite struct {
|
||||
|
||||
func (s *testSuite) TestRoundTrip() {
|
||||
spec := fmt.Sprintf("ldb:%s::hr", s.LdbDir)
|
||||
out := s.Run(main, []string{"-ds", spec, "list-persons"})
|
||||
s.Equal("No people found\n", out)
|
||||
stdout, stderr := s.Run(main, []string{"-ds", spec, "list-persons"})
|
||||
s.Equal("No people found\n", stdout)
|
||||
s.Equal("", stderr)
|
||||
|
||||
out = s.Run(main, []string{"-ds", spec, "add-person", "42", "Benjamin Kalman", "Programmer, Barista"})
|
||||
s.Equal("", out)
|
||||
stdout, stderr = s.Run(main, []string{"-ds", spec, "add-person", "42", "Benjamin Kalman", "Programmer, Barista"})
|
||||
s.Equal("", stdout)
|
||||
s.Equal("", stderr)
|
||||
|
||||
out = s.Run(main, []string{"-ds", spec, "add-person", "43", "Abigail Boodman", "Chief Architect"})
|
||||
s.Equal("", out)
|
||||
stdout, stderr = s.Run(main, []string{"-ds", spec, "add-person", "43", "Abigail Boodman", "Chief Architect"})
|
||||
s.Equal("", stdout)
|
||||
s.Equal("", stderr)
|
||||
|
||||
out = s.Run(main, []string{"-ds", spec, "list-persons"})
|
||||
stdout, stderr = s.Run(main, []string{"-ds", spec, "list-persons"})
|
||||
s.Equal(`Benjamin Kalman (id: 42, title: Programmer, Barista)
|
||||
Abigail Boodman (id: 43, title: Chief Architect)
|
||||
`, out)
|
||||
`, stdout)
|
||||
s.Equal("", stderr)
|
||||
|
||||
}
|
||||
|
||||
func (s *testSuite) TestReadCanned() {
|
||||
@@ -49,13 +54,14 @@ func (s *testSuite) TestReadCanned() {
|
||||
// Have to copy the canned data elsewhere because just reading the database modifies it.
|
||||
_, err = exec.Command("cp", "-r", p, dst).Output()
|
||||
s.NoError(err)
|
||||
out := s.Run(main, []string{"-ds", fmt.Sprintf("ldb:%s/test-data::hr", dst), "list-persons"})
|
||||
stdout, stderr := s.Run(main, []string{"-ds", fmt.Sprintf("ldb:%s/test-data::hr", dst), "list-persons"})
|
||||
s.Equal(`Aaron Boodman (id: 7, title: Chief Evangelism Officer)
|
||||
Samuel Boodman (id: 13, title: VP, Culture)
|
||||
`, out)
|
||||
`, stdout)
|
||||
s.Equal("", stderr)
|
||||
}
|
||||
|
||||
func (s *testSuite) TestInvalidDatasetSpec() {
|
||||
// Should not crash
|
||||
_ = s.Run(main, []string{"-ds", "invalid-dataset", "list-persons"})
|
||||
_, _ = s.Run(main, []string{"-ds", "invalid-dataset", "list-persons"})
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ func main() {
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
|
||||
spec.RegisterDatabaseFlags()
|
||||
spec.RegisterDatabaseFlags(flag.CommandLine)
|
||||
flag.Parse()
|
||||
|
||||
if len(flag.Args()) != 2 {
|
||||
|
||||
@@ -33,7 +33,7 @@ func main() {
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
|
||||
spec.RegisterDatabaseFlags()
|
||||
spec.RegisterDatabaseFlags(flag.CommandLine)
|
||||
flag.Parse()
|
||||
|
||||
if flag.NArg() != 2 {
|
||||
|
||||
@@ -51,7 +51,8 @@ func (a refIndexList) Less(i, j int) bool { return a[i].index < a[j].index }
|
||||
|
||||
func main() {
|
||||
err := d.Try(func() {
|
||||
spec.RegisterDatabaseFlags()
|
||||
spec.RegisterDatabaseFlags(flag.CommandLine)
|
||||
profile.RegisterProfileFlags(flag.CommandLine)
|
||||
flag.Usage = customUsage
|
||||
flag.Parse()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user