Commit cf299b65 authored by Kirill Smelkov's avatar Kirill Smelkov

X move prog infrastructure -> lab.nexedi.com/kirr/go123/prog

parent 59e79dd7
...@@ -20,19 +20,19 @@ ...@@ -20,19 +20,19 @@
// Package neotools provides tools for running and managing NEO databases. // Package neotools provides tools for running and managing NEO databases.
package neotools package neotools
import "lab.nexedi.com/kirr/neo/go/zodb/zodbtools" import "lab.nexedi.com/kirr/go123/prog"
var commands = zodbtools.CommandRegistry{ var commands = prog.CommandRegistry{
{"master", masterSummary, masterUsage, masterMain}, {"master", masterSummary, masterUsage, masterMain},
{"storage", storageSummary, storageUsage, storageMain}, {"storage", storageSummary, storageUsage, storageMain},
} }
var helpTopics = zodbtools.HelpRegistry{ var helpTopics = prog.HelpRegistry{
// XXX for now empty // XXX for now empty
} }
// main neo driver // main neo driver
var Prog = zodbtools.MainProg{ var Prog = prog.MainProg{
Name: "neo", Name: "neo",
Summary: "Neo is a tool for running NEO services and commands", Summary: "Neo is a tool for running NEO services and commands",
Commands: commands, Commands: commands,
......
...@@ -27,9 +27,9 @@ import ( ...@@ -27,9 +27,9 @@ import (
"io" "io"
"os" "os"
"lab.nexedi.com/kirr/go123/prog"
"lab.nexedi.com/kirr/neo/go/neo/server" "lab.nexedi.com/kirr/neo/go/neo/server"
"lab.nexedi.com/kirr/neo/go/xcommon/xnet" "lab.nexedi.com/kirr/neo/go/xcommon/xnet"
zt "lab.nexedi.com/kirr/neo/go/zodb/zodbtools"
) )
const masterSummary = "run master node" const masterSummary = "run master node"
...@@ -53,13 +53,13 @@ func masterMain(argv []string) { ...@@ -53,13 +53,13 @@ func masterMain(argv []string) {
flags.Parse(argv[1:]) flags.Parse(argv[1:])
if *cluster == "" { if *cluster == "" {
zt.Fatal("cluster name must be provided") prog.Fatal("cluster name must be provided")
} }
argv = flags.Args() argv = flags.Args()
if len(argv) < 1 { if len(argv) < 1 {
flags.Usage() flags.Usage()
zt.Exit(2) prog.Exit(2)
} }
net := xnet.NetPlain("tcp") // TODO + TLS; not only "tcp" ? net := xnet.NetPlain("tcp") // TODO + TLS; not only "tcp" ?
...@@ -77,6 +77,6 @@ func masterMain(argv []string) { ...@@ -77,6 +77,6 @@ func masterMain(argv []string) {
err := masterSrv.Run(ctx) err := masterSrv.Run(ctx)
if err != nil { if err != nil {
zt.Fatal(err) prog.Fatal(err)
} }
} }
...@@ -29,10 +29,10 @@ import ( ...@@ -29,10 +29,10 @@ import (
"runtime" "runtime"
"strings" "strings"
"lab.nexedi.com/kirr/go123/prog"
"lab.nexedi.com/kirr/neo/go/neo/server" "lab.nexedi.com/kirr/neo/go/neo/server"
"lab.nexedi.com/kirr/neo/go/xcommon/xnet" "lab.nexedi.com/kirr/neo/go/xcommon/xnet"
"lab.nexedi.com/kirr/neo/go/zodb/storage/fs1" "lab.nexedi.com/kirr/neo/go/zodb/storage/fs1"
zt "lab.nexedi.com/kirr/neo/go/zodb/zodbtools"
) )
const storageSummary = "run storage node" const storageSummary = "run storage node"
...@@ -57,15 +57,15 @@ func storageMain(argv []string) { ...@@ -57,15 +57,15 @@ func storageMain(argv []string) {
flags.Parse(argv[1:]) flags.Parse(argv[1:])
if *cluster == "" { if *cluster == "" {
zt.Fatal("cluster name must be provided") prog.Fatal("cluster name must be provided")
} }
masterv := strings.Split(*masters, ",") masterv := strings.Split(*masters, ",")
if len(masterv) == 0 { if len(masterv) == 0 {
zt.Fatal("master list must be provided") prog.Fatal("master list must be provided")
} }
if len(masterv) > 1 { if len(masterv) > 1 {
zt.Fatal("BUG neo/go POC currently supports only 1 master") prog.Fatal("BUG neo/go POC currently supports only 1 master")
} }
master := masterv[0] master := masterv[0]
...@@ -73,7 +73,7 @@ func storageMain(argv []string) { ...@@ -73,7 +73,7 @@ func storageMain(argv []string) {
argv = flags.Args() argv = flags.Args()
if len(argv) < 1 { if len(argv) < 1 {
flags.Usage() flags.Usage()
zt.Exit(2) prog.Exit(2)
} }
// adjust GOMAXPROCS *= N (a lot of file IO) because file IO really consumes OS threads; details: // adjust GOMAXPROCS *= N (a lot of file IO) because file IO really consumes OS threads; details:
...@@ -88,7 +88,7 @@ func storageMain(argv []string) { ...@@ -88,7 +88,7 @@ func storageMain(argv []string) {
// XXX hack to use existing zodb storage for data // XXX hack to use existing zodb storage for data
zstor, err := fs1.Open(context.Background(), argv[0]) zstor, err := fs1.Open(context.Background(), argv[0])
if err != nil { if err != nil {
zt.Fatal(err) prog.Fatal(err)
} }
net := xnet.NetPlain("tcp") // TODO + TLS; not only "tcp" ? net := xnet.NetPlain("tcp") // TODO + TLS; not only "tcp" ?
...@@ -106,6 +106,6 @@ func storageMain(argv []string) { ...@@ -106,6 +106,6 @@ func storageMain(argv []string) {
err = storSrv.Run(ctx) err = storSrv.Run(ctx)
if err != nil { if err != nil {
zt.Fatal(err) prog.Fatal(err)
} }
} }
...@@ -58,8 +58,8 @@ import ( ...@@ -58,8 +58,8 @@ import (
"golang.org/x/tools/go/loader" "golang.org/x/tools/go/loader"
"lab.nexedi.com/kirr/go123/prog"
"lab.nexedi.com/kirr/go123/xerr" "lab.nexedi.com/kirr/go123/xerr"
zt "lab.nexedi.com/kirr/neo/go/zodb/zodbtools"
) )
// traceEvent represents 1 trace:event declaration // traceEvent represents 1 trace:event declaration
...@@ -940,18 +940,18 @@ func genMain(argv []string) { ...@@ -940,18 +940,18 @@ func genMain(argv []string) {
argv = flags.Args() argv = flags.Args()
if len(argv) < 1 { if len(argv) < 1 {
flags.Usage() flags.Usage()
zt.Exit(2) prog.Exit(2)
} }
pkgpath := argv[0] pkgpath := argv[0]
cwd, err := os.Getwd() cwd, err := os.Getwd()
if err != nil { if err != nil {
zt.Fatal(err) prog.Fatal(err)
} }
err = tracegen(pkgpath, &build.Default, cwd) err = tracegen(pkgpath, &build.Default, cwd)
if err != nil { if err != nil {
zt.Fatal(err) prog.Fatal(err)
} }
} }
...@@ -1008,33 +1008,33 @@ func listMain(argv []string) { ...@@ -1008,33 +1008,33 @@ func listMain(argv []string) {
argv = flags.Args() argv = flags.Args()
if len(argv) < 1 { if len(argv) < 1 {
flags.Usage() flags.Usage()
zt.Exit(2) prog.Exit(2)
} }
pkgpath := argv[0] pkgpath := argv[0]
cwd, err := os.Getwd() cwd, err := os.Getwd()
if err != nil { if err != nil {
zt.Fatal(err) prog.Fatal(err)
} }
err = tracelist(os.Stdout, pkgpath, &build.Default, cwd) err = tracelist(os.Stdout, pkgpath, &build.Default, cwd)
if err != nil { if err != nil {
zt.Fatal(err) prog.Fatal(err)
} }
} }
// ---- main driver ---- // ---- main driver ----
var commands = zt.CommandRegistry{ var commands = prog.CommandRegistry{
{"gen", genSummary, genUsage, genMain}, {"gen", genSummary, genUsage, genMain},
{"list", listSummary, listUsage, listMain}, {"list", listSummary, listUsage, listMain},
} }
var helpTopics = zt.HelpRegistry{ var helpTopics = prog.HelpRegistry{
// XXX for now empty // XXX for now empty
} }
var prog = zt.MainProg{ var gotrace = prog.MainProg{
Name: "gotrace", Name: "gotrace",
Summary: "Gotrace is a program to support and interact with go tracing subsystem", Summary: "Gotrace is a program to support and interact with go tracing subsystem",
Commands: commands, Commands: commands,
...@@ -1044,5 +1044,5 @@ var prog = zt.MainProg{ ...@@ -1044,5 +1044,5 @@ var prog = zt.MainProg{
func main() { func main() {
log.SetFlags(0) log.SetFlags(0)
log.SetPrefix("gotrace: ") log.SetPrefix("gotrace: ")
prog.Main() gotrace.Main()
} }
...@@ -29,8 +29,8 @@ import ( ...@@ -29,8 +29,8 @@ import (
"lab.nexedi.com/kirr/neo/go/zodb" "lab.nexedi.com/kirr/neo/go/zodb"
"lab.nexedi.com/kirr/neo/go/zodb/storage/fs1" "lab.nexedi.com/kirr/neo/go/zodb/storage/fs1"
zt "lab.nexedi.com/kirr/neo/go/zodb/zodbtools"
"lab.nexedi.com/kirr/go123/prog"
"lab.nexedi.com/kirr/go123/xbytes" "lab.nexedi.com/kirr/go123/xbytes"
"lab.nexedi.com/kirr/go123/xerr" "lab.nexedi.com/kirr/go123/xerr"
"lab.nexedi.com/kirr/go123/xfmt" "lab.nexedi.com/kirr/go123/xfmt"
...@@ -309,7 +309,7 @@ func dumpMain(argv []string) { ...@@ -309,7 +309,7 @@ func dumpMain(argv []string) {
argv = flags.Args() argv = flags.Args()
if len(argv) < 1 { if len(argv) < 1 {
flags.Usage() flags.Usage()
zt.Exit(2) prog.Exit(2)
} }
storPath := argv[0] storPath := argv[0]
...@@ -322,7 +322,7 @@ func dumpMain(argv []string) { ...@@ -322,7 +322,7 @@ func dumpMain(argv []string) {
err := Dump(os.Stdout, storPath, fs1.IterForward, d) err := Dump(os.Stdout, storPath, fs1.IterForward, d)
if err != nil { if err != nil {
zt.Fatal(err) prog.Fatal(err)
} }
} }
...@@ -407,12 +407,12 @@ func tailMain(argv []string) { ...@@ -407,12 +407,12 @@ func tailMain(argv []string) {
argv = flags.Args() argv = flags.Args()
if len(argv) < 1 { if len(argv) < 1 {
flags.Usage() flags.Usage()
zt.Exit(2) prog.Exit(2)
} }
storPath := argv[0] storPath := argv[0]
err := Dump(os.Stdout, storPath, fs1.IterBackward, &DumperFsTail{Ntxn: ntxn}) err := Dump(os.Stdout, storPath, fs1.IterBackward, &DumperFsTail{Ntxn: ntxn})
if err != nil { if err != nil {
zt.Fatal(err) prog.Fatal(err)
} }
} }
...@@ -27,8 +27,8 @@ import ( ...@@ -27,8 +27,8 @@ import (
"os" "os"
"time" "time"
"lab.nexedi.com/kirr/go123/prog"
"lab.nexedi.com/kirr/neo/go/zodb/storage/fs1" "lab.nexedi.com/kirr/neo/go/zodb/storage/fs1"
zt "lab.nexedi.com/kirr/neo/go/zodb/zodbtools"
) )
// Reindex rebuilds index for FileStorage file @ path // Reindex rebuilds index for FileStorage file @ path
...@@ -73,13 +73,13 @@ func reindexMain(argv []string) { ...@@ -73,13 +73,13 @@ func reindexMain(argv []string) {
argv = flags.Args() argv = flags.Args()
if len(argv) < 1 { if len(argv) < 1 {
flags.Usage() flags.Usage()
zt.Exit(2) prog.Exit(2)
} }
storPath := argv[0] storPath := argv[0]
fi, err := os.Stat(storPath) fi, err := os.Stat(storPath)
if err != nil { if err != nil {
zt.Fatal(err) prog.Fatal(err)
} }
// progress display // progress display
...@@ -124,7 +124,7 @@ func reindexMain(argv []string) { ...@@ -124,7 +124,7 @@ func reindexMain(argv []string) {
} }
if err != nil { if err != nil {
zt.Fatal(err) prog.Fatal(err)
} }
if !quiet { if !quiet {
...@@ -176,7 +176,7 @@ func verifyIdxMain(argv []string) { ...@@ -176,7 +176,7 @@ func verifyIdxMain(argv []string) {
argv = flags.Args() argv = flags.Args()
if len(argv) < 1 { if len(argv) < 1 {
flags.Usage() flags.Usage()
zt.Exit(2) prog.Exit(2)
} }
storPath := argv[0] storPath := argv[0]
...@@ -225,7 +225,7 @@ func verifyIdxMain(argv []string) { ...@@ -225,7 +225,7 @@ func verifyIdxMain(argv []string) {
} }
if err != nil { if err != nil {
zt.Fatal(err) prog.Fatal(err)
} }
if !quiet { if !quiet {
......
...@@ -20,9 +20,9 @@ ...@@ -20,9 +20,9 @@
// Package fs1tools provides tools for managing and maintaining ZODB FileStorage v1 databases. // Package fs1tools provides tools for managing and maintaining ZODB FileStorage v1 databases.
package fs1tools package fs1tools
import "lab.nexedi.com/kirr/neo/go/zodb/zodbtools" import "lab.nexedi.com/kirr/go123/prog"
var commands = zodbtools.CommandRegistry{ var commands = prog.CommandRegistry{
{"dump", dumpSummary, dumpUsage, dumpMain}, {"dump", dumpSummary, dumpUsage, dumpMain},
{"tail", tailSummary, tailUsage, tailMain}, {"tail", tailSummary, tailUsage, tailMain},
// + fsstats? (fsstats.py) // + fsstats? (fsstats.py)
...@@ -35,12 +35,12 @@ var commands = zodbtools.CommandRegistry{ ...@@ -35,12 +35,12 @@ var commands = zodbtools.CommandRegistry{
// XXX repozo ? // XXX repozo ?
} }
var helpTopics = zodbtools.HelpRegistry{ var helpTopics = prog.HelpRegistry{
// XXX for now empty // XXX for now empty
} }
// main fs1 driver // main fs1 driver
var Prog = zodbtools.MainProg{ var Prog = prog.MainProg{
Name: "fs1", Name: "fs1",
Summary: "Fs1 is a tool for managing and maintaining ZODB FileStorage v1 databases", Summary: "Fs1 is a tool for managing and maintaining ZODB FileStorage v1 databases",
Commands: commands, Commands: commands,
......
...@@ -27,6 +27,7 @@ import ( ...@@ -27,6 +27,7 @@ import (
"io" "io"
"os" "os"
"lab.nexedi.com/kirr/go123/prog"
"lab.nexedi.com/kirr/neo/go/zodb" "lab.nexedi.com/kirr/neo/go/zodb"
) )
...@@ -98,33 +99,33 @@ func catobjMain(argv []string) { ...@@ -98,33 +99,33 @@ func catobjMain(argv []string) {
argv = flags.Args() argv = flags.Args()
if len(argv) < 2 { if len(argv) < 2 {
flags.Usage() flags.Usage()
Exit(2) prog.Exit(2)
} }
storUrl := argv[0] storUrl := argv[0]
if hashOnly && raw { if hashOnly && raw {
Fatal("-hashonly & -raw are incompatible") prog.Fatal("-hashonly & -raw are incompatible")
} }
xidv := []zodb.Xid{} xidv := []zodb.Xid{}
for _, arg := range argv[1:] { for _, arg := range argv[1:] {
xid, err := zodb.ParseXid(arg) xid, err := zodb.ParseXid(arg)
if err != nil { if err != nil {
Fatal(err) // XXX recheck prog.Fatal(err) // XXX recheck
} }
xidv = append(xidv, xid) xidv = append(xidv, xid)
} }
if raw && len(xidv) > 1 { if raw && len(xidv) > 1 {
Fatal("only 1 object allowed with -raw") prog.Fatal("only 1 object allowed with -raw")
} }
ctx := context.Background() ctx := context.Background()
stor, err := zodb.OpenStorageURL(ctx, storUrl) // TODO read-only stor, err := zodb.OpenStorageURL(ctx, storUrl) // TODO read-only
if err != nil { if err != nil {
Fatal(err) prog.Fatal(err)
} }
// TODO defer stor.Close() // TODO defer stor.Close()
...@@ -139,7 +140,7 @@ func catobjMain(argv []string) { ...@@ -139,7 +140,7 @@ func catobjMain(argv []string) {
for _, xid := range xidv { for _, xid := range xidv {
err = catobj(xid) err = catobj(xid)
if err != nil { if err != nil {
Fatal(err) prog.Fatal(err)
} }
} }
} }
// Copyright (C) 2017 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com>
//
// This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your
// option) any later version, as published by the Free Software Foundation.
//
// You can also Link and Combine this program with other software covered by
// the terms of any of the Free Software licenses or any of the Open Source
// Initiative approved licenses and Convey the resulting work. Corresponding
// source of such a combination shall include the source code for all other
// software used.
//
// This program is distributed WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// See COPYING file for full licensing terms.
// See https://www.nexedi.com/licensing for rationale and options.
package zodbtools
// infrastructure to organize main driver program
import (
"flag"
"fmt"
"io"
"log"
"os"
"runtime"
"runtime/pprof"
"runtime/trace"
//"lab.nexedi.com/kirr/neo/go/xcommon/log"
)
// Command describes one zodb subcommand
type Command struct {
Name string
Summary string
Usage func (w io.Writer)
Main func (argv []string)
}
// CommandRegistry is ordered collection of Commands
type CommandRegistry []Command
// Lookup returns Command with corresponding name or nil
func (cmdv CommandRegistry) Lookup(command string) *Command {
for i := range cmdv {
if cmdv[i].Name == command {
return &cmdv[i]
}
}
return nil
}
// HelpTopic describes one help topic
type HelpTopic struct {
Name string
Summary string
Text string
}
// HelpRegistry is ordered collection of HelpTopics
type HelpRegistry []HelpTopic
// Lookup returns HelpTopic with corresponding name or nil
func (helpv HelpRegistry) Lookup(topic string) *HelpTopic {
for i := range helpv {
if helpv[i].Name == topic {
return &helpv[i]
}
}
return nil
}
// ----------------------------------------
// MainProg defines a program to run with subcommands and help topics.
type MainProg struct {
Name string // name of the program, e.g. "zodb"
Summary string // 1-line summary of what program does
Commands CommandRegistry // provided subcommands
HelpTopics HelpRegistry // provided help topics
}
// Exit is like os.Exit but makes sure deferred functions are run.
// Exit should be called from main goroutine.
func Exit(code int) {
panic(&programExit{code})
}
// Fatal is like log.Fatal but makes sure deferred functions are run.
// Fatal should be called from main goroutine.
func Fatal(v ...interface{}) {
log.Print(v...)
Exit(1)
}
// programExit is thrown when Exit or Fatal are called
type programExit struct {
code int
}
// Main is the main entry point for the program. Call it from main.
//
// Do not call os.Exit or log.Fatal from your program. Instead use Exit and
// Fatal from zodbtools package so that deferred functions setup by Main could
// be run.
func (prog *MainProg) Main() {
// handle exit throw-requests
defer func() {
r := recover()
if e, _ := r.(*programExit); e != nil {
// TODO log.Flush()
os.Exit(e.code)
}
if r != nil {
panic(r)
}
}()
prog.main()
}
func (prog *MainProg) main() {
flag.Usage = prog.usage
cpuprofile := flag.String("cpuprofile", "", "write cpu profile to `file`")
memprofile := flag.String("memprofile", "", "write memory profile to `file`")
traceout := flag.String("trace", "", "write execution trace to `file`")
flag.Parse()
argv := flag.Args()
if len(argv) == 0 {
prog.usage()
Exit(2)
}
command := argv[0]
// handle common options
if *cpuprofile != "" {
f, err := os.Create(*cpuprofile)
if err != nil {
Fatal("could not create CPU profile: ", err)
}
if err := pprof.StartCPUProfile(f); err != nil {
Fatal("could not start CPU profile: ", err)
}
defer pprof.StopCPUProfile()
}
defer func() {
if *memprofile != "" {
f, err := os.Create(*memprofile)
if err != nil {
Fatal("could not create memory profile: ", err)
}
runtime.GC() // get up-to-date statistics
if err := pprof.WriteHeapProfile(f); err != nil {
Fatal("could not write memory profile: ", err)
}
f.Close()
}
}()
if *traceout != "" {
f, err := os.Create(*traceout)
if err != nil {
Fatal("could not create trace: ", err)
}
defer func() {
if err := f.Close(); err != nil {
Fatal("could not close trace: ", err)
}
}()
if err := trace.Start(f); err != nil {
Fatal("could not start trace: ", err)
}
defer trace.Stop()
}
// help on a topic
if command == "help" {
prog.help(argv)
return
}
// run subcommand
cmd := prog.Commands.Lookup(command)
if cmd == nil {
fmt.Fprintf(os.Stderr, "%s: unknown subcommand \"%s\"\n", prog.Name, command)
fmt.Fprintf(os.Stderr, "Run '%s help' for usage.\n", prog.Name)
Exit(2)
}
cmd.Main(argv)
}
// usage shows usage text for whole program
func (prog *MainProg) usage() {
w := os.Stderr
fmt.Fprintf(w,
`%s.
Usage:
%s [options] command [arguments]
The commands are:
`, prog.Summary, prog.Name)
// to lalign commands & help summaries
nameWidth := 0
for _, cmd := range prog.Commands {
if len(cmd.Name) > nameWidth {
nameWidth = len(cmd.Name)
}
}
for _, topic := range prog.helpTopics() {
if len(topic.Name) > nameWidth {
nameWidth = len(topic.Name)
}
}
for _, cmd := range prog.Commands {
fmt.Fprintf(w, "\t%-*s %s\n", nameWidth, cmd.Name, cmd.Summary)
}
fmt.Fprintf(w,
`
Use "%s help [command]" for more information about a command.
`, prog.Name)
if len(prog.helpTopics()) > 0 {
fmt.Fprintf(w,
`
Additional help topics:
`)
for _, topic := range prog.helpTopics() {
fmt.Fprintf(w, "\t%-*s %s\n", nameWidth, topic.Name, topic.Summary)
}
fmt.Fprintf(w,
`
Use "%s help [topic]" for more information about that topic.
`, prog.Name)
}
}
// help shows general help or help for a command/topic
func (prog *MainProg) help(argv []string) {
if len(argv) < 2 { // help topic ...
prog.usage()
Exit(2)
}
topic := argv[1]
// topic can either be a command name or a help topic
command := prog.Commands.Lookup(topic)
if command != nil {
command.Usage(os.Stdout)
Exit(0)
}
helpTopic := prog.helpTopics().Lookup(topic)
if helpTopic != nil {
fmt.Println(helpTopic.Text)
Exit(0)
}
fmt.Fprintf(os.Stderr, "Unknown help topic `%s`. Run '%s help'.\n", topic, prog.Name)
Exit(2)
}
// helpTopics returns provided help topics augmented with help on common topics
// provided by zodbtools driver
func (prog *MainProg) helpTopics() HelpRegistry {
return append(helpCommon, prog.HelpTopics...)
}
var helpCommon = HelpRegistry{
{"options", "options common to all commands", helpOptions},
}
const helpOptions =
`Options common to all commands:
-cpuprofile <file> write cpu profile to <file>
-memprofile <file> write memory profile to <file>
TODO also document glog options
`
...@@ -46,8 +46,8 @@ import ( ...@@ -46,8 +46,8 @@ import (
"io" "io"
"os" "os"
"lab.nexedi.com/kirr/go123/prog"
"lab.nexedi.com/kirr/go123/xfmt" "lab.nexedi.com/kirr/go123/xfmt"
"lab.nexedi.com/kirr/neo/go/zodb" "lab.nexedi.com/kirr/neo/go/zodb"
) )
...@@ -234,7 +234,7 @@ func dumpMain(argv []string) { ...@@ -234,7 +234,7 @@ func dumpMain(argv []string) {
argv = flags.Args() argv = flags.Args()
if len(argv) < 1 { if len(argv) < 1 {
flags.Usage() flags.Usage()
Exit(2) prog.Exit(2)
} }
storUrl := argv[0] storUrl := argv[0]
...@@ -244,17 +244,17 @@ func dumpMain(argv []string) { ...@@ -244,17 +244,17 @@ func dumpMain(argv []string) {
tidMin, tidMax, err := zodb.ParseTidRange(tidRange) tidMin, tidMax, err := zodb.ParseTidRange(tidRange)
if err != nil { if err != nil {
Fatal(err) // XXX recheck prog.Fatal(err) // XXX recheck
} }
stor, err := zodb.OpenStorageURL(context.Background(), storUrl) // TODO read-only stor, err := zodb.OpenStorageURL(context.Background(), storUrl) // TODO read-only
if err != nil { if err != nil {
Fatal(err) prog.Fatal(err)
} }
// TODO defer stor.Close() // TODO defer stor.Close()
err = Dump(os.Stdout, stor, tidMin, tidMax, hashOnly) err = Dump(os.Stdout, stor, tidMin, tidMax, hashOnly)
if err != nil { if err != nil {
Fatal(err) prog.Fatal(err)
} }
} }
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
package zodbtools package zodbtools
// registry for all help topics // registry for all help topics
import "lab.nexedi.com/kirr/go123/prog"
const helpZURL = const helpZURL =
`Almost every zodb command works with a database. `Almost every zodb command works with a database.
A database can be specified by way of providing URL for its storage. A database can be specified by way of providing URL for its storage.
...@@ -57,7 +59,7 @@ const helpXid = ...@@ -57,7 +59,7 @@ const helpXid =
// TODO dump format // TODO dump format
var helpTopics = HelpRegistry{ var helpTopics = prog.HelpRegistry{
{"zurl", "specifying database URL", helpZURL}, {"zurl", "specifying database URL", helpZURL},
{"xid", "specifying object address", helpXid}, {"xid", "specifying object address", helpXid},
} }
...@@ -28,6 +28,7 @@ import ( ...@@ -28,6 +28,7 @@ import (
"io" "io"
"os" "os"
"lab.nexedi.com/kirr/go123/prog"
"lab.nexedi.com/kirr/neo/go/zodb" "lab.nexedi.com/kirr/neo/go/zodb"
) )
...@@ -116,7 +117,7 @@ func infoMain(argv []string) { ...@@ -116,7 +117,7 @@ func infoMain(argv []string) {
argv = flags.Args() argv = flags.Args()
if len(argv) < 1 { if len(argv) < 1 {
flags.Usage() flags.Usage()
Exit(2) prog.Exit(2)
} }
storUrl := argv[0] storUrl := argv[0]
...@@ -124,11 +125,11 @@ func infoMain(argv []string) { ...@@ -124,11 +125,11 @@ func infoMain(argv []string) {
stor, err := zodb.OpenStorageURL(ctx, storUrl) // TODO read-only stor, err := zodb.OpenStorageURL(ctx, storUrl) // TODO read-only
if err != nil { if err != nil {
Fatal(err) prog.Fatal(err)
} }
err = Info(ctx, os.Stdout, stor, argv[1:]) err = Info(ctx, os.Stdout, stor, argv[1:])
if err != nil { if err != nil {
Fatal(err) prog.Fatal(err)
} }
} }
...@@ -20,8 +20,10 @@ ...@@ -20,8 +20,10 @@
// Package zodbtools provides tools for managing ZODB databases // Package zodbtools provides tools for managing ZODB databases
package zodbtools package zodbtools
import "lab.nexedi.com/kirr/go123/prog"
// registry of all zodbtools commands // registry of all zodbtools commands
var commands = CommandRegistry{ var commands = prog.CommandRegistry{
// NOTE the order commands are listed here is the order how they will appear in help // NOTE the order commands are listed here is the order how they will appear in help
// TODO analyze ? // TODO analyze ?
// TODO cmp // TODO cmp
...@@ -31,7 +33,7 @@ var commands = CommandRegistry{ ...@@ -31,7 +33,7 @@ var commands = CommandRegistry{
} }
// main zodbtools driver // main zodbtools driver
var Prog = MainProg{ var Prog = prog.MainProg{
Name: "zodb", Name: "zodb",
Summary: "Zodb is a tool for managing ZODB databases", Summary: "Zodb is a tool for managing ZODB databases",
Commands: commands, Commands: commands,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment